c++ - 使用可变参数模板(gcc、clang)的成员函数指针包装器

标签 c++ c++11 templates variadic-templates pointer-to-member

为什么以下代码在 gcc 或 clang 下都无法编译:

class Foo {
public:
    void bar(int) {}
};

template< class T, typename ...Args, void(T::*Member)(Args...) >
void member_dispatch(Args&&... args, void* userdata)
{
    T* obj = static_cast<T*>(userdata);
    (obj->*Member)(std::forward<Args>(args)...);
}

int main()
{
    Foo foo;
    member_dispatch<Foo, int, &Foo::bar>(1, &foo);
    return 0;
}

参见例如here .

这个问题可能与this合并一,虽然在这里我从 gcc 和 clang(而不是 VS)得到不清楚的编译错误。

最佳答案

当您显式指定类型时,参数包是贪婪的。 &Foo::bar 将被解析为 typename ...Args 的一部分,这会导致错误。

正确的写法是放在函数参数列表中,而不是非类型模板参数。

template< class T, typename ...Args>
void member_dispatch(Args&&... args, void(T::*Member)(Args...), void* userdata)
{
    T* obj = static_cast<T*>(userdata);
    (obj->*Member)(std::forward<Args>(args)...);
}

int main()
{
    Foo foo;
    member_dispatch<Foo, int>(1, &Foo::bar, &foo);
    return 0;
}

更好的方法:

最好利用 C++ 的模板参数推导。但是这里你没有把参数 pact 放在函数参数列表的末尾,这是一个非推导上下文。所以我建议你重新排序,这样你就不需要指定模板参数了:

template<class T, class K, typename ...Args>
void member_dispatch(K T::*ptr, void* userdata, Args&&... args)
{
    T* obj = static_cast<T*>(userdata);
    (obj->*ptr)(std::forward<Args>(args)...);
}

int main()
{
    Foo foo;
    member_dispatch(&Foo::bar, &foo, 1);
    return 0;
}

关于c++ - 使用可变参数模板(gcc、clang)的成员函数指针包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49464538/

相关文章:

c++ - 使用带有 valarray 的 C++ 标准库算法

c++ - 你可以将 pimpl-Class 放入 vector 中吗

wpf - 在 WPF : how to disable the animation when the button after be pressed? 中

c++ - 返回 std::function 的类 std::bind 函数

c++ - 自动扣除部分模板类型

c++ - 基于 C++ 中的多个事物进行排序

c++ - 为什么在给定 T&& 和 const T& 重载的情况下,const 左值与 const 右值的绑定(bind)不同?

c++ - 使用 boost 序列化从 XML 加载类

c++ - C++ 模板中的函数签名

c++ - std::vector< MyObj* > 到 std::vector< MyObj Const * >,如何没有循环?