将可变参数类模板的子类传递给仅接受基类的函数(通过参数包推导/推理)

发布于 2024-09-18 03:34:26 字数 1430 浏览 4 评论 0原文

**我收到了一些建议,使我的函数成为纯通用函数,这会起作用,但我更愿意将该函数限制为仅接受 Base 及其子函数。

无法创建一个可以接受可变参数模板类基类型参数的函数,而该函数实际上将使用从 Base 派生的类来调用。我尝试过一些事情。这是总体思路。给出:

template<typename... Args> struct Base {
    std::tuple<Args...> data;
    ... //other stuff
};

struct DerivedA : Base<string, int> {
};

struct DerviedB : Base<bool, string, int> {
};

创建执行此操作的函数的正确方法是什么:

string moosh_together(Base A, Base B) { //I only need access to Base's members
    return get<0>(A.data) + get<1>(B.data);
}

main() {
    DerivedA aThing;
        get<0>(aThing.data) = "foo";
    DerivedB bThing;
        get<1>(bThing.data) = "bar'd";
    cout << moosh_together(aThing, bThing) << endl;
}

输出:

foobar'd

我尝试了 moosh_together 函数的一些变体,但没有一个起作用。保留上面的内容会生成有关缺少模板参数的编译器错误。我不确定如何将定义 DerivedA 和 DerivedB 的模板参数传递给函数。

我尝试过的其他方法(霰弹枪方法):

string moosh_together(Base<> A, Base<> B) {}
//err: conversion from 'DerivedA' to non-scalar type 'Base<>' requested

template<Base<typename... Args> T1, Base<typename... Args> T2>
string moosh_together(T1 A, T2 B) {}
//err: expected paramter pack before '...'

template<Base<Args...> T1, Base<Args...> T2>
string moosh_together(T1 A, T2 B) {}
//err: 'Args' was not declared in this scope

**I've gotten a few suggestions to make my function pure generic, which would work, but I'd prefer limiting the function to only accept Base and its children.

Having trouble making a function that can accept arguments of a variadic template class base type, while the function will actually be called with classes that derive from Base. I've tried a few things. Here's the general idea. Given:

template<typename... Args> struct Base {
    std::tuple<Args...> data;
    ... //other stuff
};

struct DerivedA : Base<string, int> {
};

struct DerviedB : Base<bool, string, int> {
};

What's the correct way to create a function that does this:

string moosh_together(Base A, Base B) { //I only need access to Base's members
    return get<0>(A.data) + get<1>(B.data);
}

main() {
    DerivedA aThing;
        get<0>(aThing.data) = "foo";
    DerivedB bThing;
        get<1>(bThing.data) = "bar'd";
    cout << moosh_together(aThing, bThing) << endl;
}

Output:

foobar'd

I've tried a few variations of the moosh_together function, none of which work. Leaving it as above generates a compiler error about missing template arguments. I'm unsure how to pass through to the function the template arguments that define DerivedA and DerivedB.

Other things I've tried (shotgun method):

string moosh_together(Base<> A, Base<> B) {}
//err: conversion from 'DerivedA' to non-scalar type 'Base<>' requested

template<Base<typename... Args> T1, Base<typename... Args> T2>
string moosh_together(T1 A, T2 B) {}
//err: expected paramter pack before '...'

template<Base<Args...> T1, Base<Args...> T2>
string moosh_together(T1 A, T2 B) {}
//err: 'Args' was not declared in this scope

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心凉 2024-09-25 03:34:40

我认为它的一般扩展是

string moosh_together(Base<T1...> A1, Base<T2...> A2, ... Base<Tn...> An) {
    return get<0>(A1.data) + get<1>(A2) + ... + get<n-1>(An.data);
}

这可以写成如下

template<int I> 
string moosh_together() { return ""; }

template<int I, typename ...Base1Ty, typename ... Bases>
string moosh_together(Base<Base1Ty...> const& base1, Bases const&... bases) {
    return get<I>(base1.data) + moosh_together<I+1>(bases...); 
}

template<typename ... Bases>
string moosh_together(Bases const&... bases) {
    return moosh_together<0>(bases...);
}

I think the general expansion of this is

string moosh_together(Base<T1...> A1, Base<T2...> A2, ... Base<Tn...> An) {
    return get<0>(A1.data) + get<1>(A2) + ... + get<n-1>(An.data);
}

This could be written as follows

template<int I> 
string moosh_together() { return ""; }

template<int I, typename ...Base1Ty, typename ... Bases>
string moosh_together(Base<Base1Ty...> const& base1, Bases const&... bases) {
    return get<I>(base1.data) + moosh_together<I+1>(bases...); 
}

template<typename ... Bases>
string moosh_together(Bases const&... bases) {
    return moosh_together<0>(bases...);
}
原来分手还会想你 2024-09-25 03:34:38

您不能在 Base 的继承层次结构中创建一个基类并将其传递给 moosh_together() 函数吗? (这里c++知识很少)

Couldn't you create a base class in the inheritance hierarchy for Base and pass that to the moosh_together() function? (Low knowledge of c++ here)

梦旅人picnic 2024-09-25 03:34:37

当您编写:string moosh_together(Base A, Base B)时,问问自己Base是什么。 Base 是一个类模板,而不是类类型。

换句话说,给定:

template <typename T>
struct foo {};

foofoo 是两种完全不同的类型,它们恰好是由同一个类模板创建的。它们没有共同的基类,并且您不能将它们简单地引用为 foo,就像您不能使用单个引用同时引用 intfloat 一样。类型。

您可以提取 Base 的非依赖部分:

struct Core
{
    string name;
};

template <typename... Args>
struct Base : Core
{
    // ...
};

然后引用 Core 部分:

// pass by reference, to avoid unnecessary copying
string moosh_together(const Core& a, const Core& b);

或者只是使该函数完全通用:

template <typename BaseOne, typename BaseTwo>
string moosh_together(const BaseOne& a, const BaseTwo& b);

并说“如果您有必要的会员,您可以使用此功能”。

When you write: string moosh_together(Base A, Base B), ask yourself what Base is. Base is a class template, not a class type.

In other words, given:

template <typename T>
struct foo {};

foo<int> and foo<float> are two totally different types, that just so happened to be made from the same class template. They have no common base class, and you cannot refer to them simply as foo anymore than you can refer to both int and float with a single type.

You could factor out the non-dependent parts of Base:

struct Core
{
    string name;
};

template <typename... Args>
struct Base : Core
{
    // ...
};

And then refer to the Core portions:

// pass by reference, to avoid unnecessary copying
string moosh_together(const Core& a, const Core& b);

Or just make the function totally generic:

template <typename BaseOne, typename BaseTwo>
string moosh_together(const BaseOne& a, const BaseTwo& b);

And say "if you have the necessary members, you can use this function".

白日梦 2024-09-25 03:34:36

编辑:

如果您需要两个参数包,则可以将它们都放入模板规范中:

template<typename... ArgsA, typename... ArgsB>
string moosh_together(const Base<ArgsA...>& A, const Base<ArgsB...>& B) {
    return get<0>(A.data) + get<1>(B.data);
}

这是可行的,因为参数包是从参数推断出来的,而不是在列表中指定。当然,您不能拥有一个依赖于多个参数包的类。

Edit:

If you need both parameter packs, you can just put both in the template specification:

template<typename... ArgsA, typename... ArgsB>
string moosh_together(const Base<ArgsA...>& A, const Base<ArgsB...>& B) {
    return get<0>(A.data) + get<1>(B.data);
}

This works because the parameter packs are inferred from arguments and not specified in a list. Naturally you can't have a class that depends on multiple parameter packs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文