使用可变参数模板(gcc、clang)的成员函数指针包装器
Member function pointer wrapper using variadic template (gcc, clang)
为什么以下代码在 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
的一部分,这会导致错误。
正确的写法是将它放在函数参数列表中,而不是 non-type 模板参数。
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 放在函数参数列表的末尾,这是一个 non-deduced 上下文。所以我建议你 re-order 它,这样你就不需要指定模板参数:
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;
}
尝试使用 class 模板而不是函数模板。
对于 none-type 模板参数,还有一个标准语法提案 "template << auto x >> "。正确的实施将简化您的库语法。
为什么以下代码在 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
的一部分,这会导致错误。
正确的写法是将它放在函数参数列表中,而不是 non-type 模板参数。
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 放在函数参数列表的末尾,这是一个 non-deduced 上下文。所以我建议你 re-order 它,这样你就不需要指定模板参数:
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;
}
尝试使用 class 模板而不是函数模板。 对于 none-type 模板参数,还有一个标准语法提案 "template << auto x >> "。正确的实施将简化您的库语法。