当前位置: 首页 > 知识库问答 >
问题:

使用成员字段调用variadic类模板的member方法

秦渝
2023-03-14

我学习了一些关于variadic模板的知识,并在Internet上搜索了一些示例,现在尝试编写一些棘手的代码来调用member一个variadic类模板的方法,其中包含一个字段。我不明白为什么它不起作用。拜托,救命。

以下是示例类:

class BarBase
{
public:
    BarBase() = default;

    virtual void call() = 0;
};

template<typename O, typename M, typename... A>
class Bar
    : public BarBase
{
public:
    Bar(O* o, M m, A&&... a)
        : BarBase()
        , m_o(o), m_m(m), m_a(std::forward<A>(a)...)
    { }

    void call() override final
    {
        callInnerWithArgsInside();
    }

private:
    void callInnerWithArgsInside()
    {
        (m_o->*m_m)(m_a); // Some errors happends here
    }

    O* m_o;
    M m_m;
    std::tuple<typename std::remove_reference<A>::type...> m_a;
};

template<typename O, typename M, typename... A>
BarBase* crateBar(O* o, M m, A&&... a)
{
    return new Bar<O, M, A...>(o, m, std::forward<A>(a)...);
}

和来自Main的呼叫:

struct Foo
{
    void foo(int ii, float ff, std::string ss)
    {
        std::cout << "called" << std::endl;
    }
};

int main()
{
    Foo f;
    int i = 10;
    float ff = 20.2f;
    std::string s = "Hello";

    BarBase* bar = crateBar(&f, &Foo::foo, i, ff, s);
    bar->call();
}

错误:

main.cpp

1>d:\drafts_tests\main.cpp(203):错误C2198:“void(__thiscall foo::*)(int,float,std::string)”:调用的参数太少

1>d:\drafts_tests\main.cpp(202):编译类模板成员函数“void bar::CallInnerWithArgsInSide(void)”时

1>与

1>[

1>o=foo

1>,m=void(__thiscall foo::*)(int,float,std::string)

1>]

1>与

1>[

1>o=foo

1>D:\drafts_tests\main.cpp(214):参见对正在编译的类模板实例化“bar”的引用

1>与

1>[

1>D:\drafts_tests\main.cpp(225):请参阅对正在编译的函数模板实例化“barbase*cratebar(O*,M,int&,float&,std::string&)”的引用

1>与

1>[

1>,m=void(__thiscall foo::*)(int,float,std::string)

1>]

===========生成:0成功,1失败,0最新,0跳过==========

共有1个答案

邓正谊
2023-03-14

您将向函数传递元组,而不是向单个类型参数传递元组。下面将向调用传递所需的类型参数

template<std::size_t... I>
void callInnerWithArgsInside2(std::index_sequence<I...>)
{
    (m_o->*m_m)(std::get<I>(m_a)...); 
}

void callInnerWithArgsInside()
{
    return callInnerWithArgsInside2( std::make_index_sequence<sizeof...(A)>());
}

现场演示


Edit1:C++11版本

我已经实现了一个C++11版本,请参阅更新的现场演示

 类似资料:
  • 我试图使用基于模板的类作为另一个类的成员。另一个类将根据其数据成员值决定基于模板的成员应该使用的数据类型。为此,我使用了一点多态性来决定实例化的运行时。 然后,打印函数将根据 T 的类型进行打印,它是 int 还是 float。此时我收到链接器错误。 错误LNK2019:未解析的外部符号" public:_ this call template dynamic::template dynamic(

  • 我有一个模板化的C++类,它也有一个模板化的成员函数。这个成员函数的模板参数以特定的方式依赖于类的模板参数(请参阅下面的代码)。我正在为其模板参数的两个不同值实例化(而不是专门化)该类。一切都在这一点上进行。但是,如果我调用模板化的成员函数,对第一个实例化对象的调用只会编译,而不会编译第二个。似乎编译器没有为模板类的第二次实例化实例化模板化成员函数。我正在使用“g++filename.cpp”编译

  • 成员函数是特定于类的函数。 它对其所属的类的任何对象进行操作,并且可以访问该对象的类的所有成员。 在对象上使用点运算符( . )调用成员函数,在该对象上操作与该对象相关的数据。 让我们在上面的概念中设置并获取类中不同类成员的值 - import std.stdio; class Box { public: double length; // Length of

  • 是否有人知道此显式特化是否有效: clang 主干 (12/3/2013) 给出以下错误: f:...\test.cpp:36:20: 错误: 从类 'O' 中出线定义 “Fun” 没有定义 1生成错误。 任何来自标准的支持参考来证明你的答案将不胜感激! 注意:我有点惊讶这是一个错误——我认为应该为任何以< code >开始实例化“Fun”的模板参数族选择专门化 这是一个叮当的错误还是我期望中的错

  • 如果这个例子比较复杂,我很抱歉,但我希望它能帮助人们更好地理解现代C++用法。所以我想让这段代码工作起来。它应该为单积分型和变分型产生特殊的lambdas,以便在硬静态转换为单积分型或软变分转换为普通型时计算项的顺序。我添加了注释,这些注释描述了我在这段代码中真正尝试做的事情。

  • 这有什么问题: 我在这里尝试过:用不同的编译器https://godbolt.org/z/NkL44s: x86-64 gcc 9.2:编译 x86-64 gcc(主干):失败 x86-64 clang 6.0.0:编译 x86-64 clang 7.0.0及更高版本:失败 x64 msvc v19.22:编译 x64 msvc v19.23(内部测试):失败 那么,为什么最近的编译器会拒绝这一点