【问题标题】:Call member method of a variadic class template with a member field使用成员字段调用可变参数类模板的成员方法
【发布时间】:2017-05-29 17:03:08
【问题描述】:

我了解了一些关于可变参数模板的知识,并在 Internet 上搜索了一些示例,现在尝试编写一些棘手的代码来调用成员一个可变参数类模板的方法及其一个字段。我不明白为什么它不起作用。请帮忙。

这里是示例类:

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): error 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> d:\drafts_tests\main.cpp(197) : 请参阅正在编译的函数模板实例化 'void Bar::callInnerWithArgsInside(void)' 的参考

1> 与

1> [

1> O=Foo

1> , M=void (__thiscall Foo::* )(int,float,std::string)

1>]

1> d:\drafts_tests\main.cpp(214) : 请参阅正在编译的类模板实例化“Bar”的参考

1> 与

1> [

1> O=Foo

1> , M=void (__thiscall Foo::* )(int,float,std::string)

1>]

1> d:\drafts_tests\main.cpp(225) : 请参阅正在编译的函数模板实例化 'BarBase *crateBar(O *,M,int &,float &,std::string &)' 的参考

1> 与

1> [

1> O=Foo

1> , M=void (__thiscall Foo::* )(int,float,std::string)

1>]

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

【问题讨论】:

  • 它到底是怎么不工作的?
  • 我想你会找到this question 一个迷人的读物。

标签: c++ c++11 variadic-templates


【解决方案1】:

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

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)>());
}

live demo


EDIT1:C++11 版本

我已经实现了一个C++11版本,见updated live demo

【讨论】:

  • 是 C++11 的东西“std::index_sequence”、“std::make_index_sequence”吗?
  • 抱歉,你是对的,那是 C++14,但我过去已经为 C++11 实现了 index_seq,请参阅 here 以获取更新的演示
猜你喜欢
  • 2012-03-13
  • 1970-01-01
  • 2017-10-18
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多