[英]C++ template argument deduction for pointers to overloaded member function
[英]Template argument deduction for member function pointers
众所周知,模板参数可以是指向成员函数的指针。
所以我可以写:
struct Bar
{
int fun(float x);
};
template <int (Bar::*FUN)(float)>
struct Foo
{ /*...*/ };
typedef Foo<&Bar::fun> FooBar;
但是如果我希望Bar
类型本身成为模板参数呢?
template <typename B, int (B::*FUN)(float)>
struct Foo
{ /*...*/ };
typedef Foo<Bar, &Bar::fun> FooBar;
现在,当我使用它,我必须写Bar
两次!
我的问题是:有没有办法强制编译器自动推导出类类型?
目标是让这个工作:
typedef Foo<&Bar::fun> FooBar;
typedef Foo<&Moo::fun> FooMoo;
简单的回答:没有。
问题是对于typedef Foo<&Bar::fun> FooBar;
要工作,模板必须有一个非类型参数,但是在声明模板时该参数的类型是未知的,这是无效的。 另一方面,类型推导从不应用于模板的参数(仅适用于函数模板的参数,但这些是函数的参数,而不是模板的参数)。
你可能应该只在那里写类名。 但是,如果你真的想避免它,你可以使用宏的邪恶魔法。 简单版本更危险:
#define TT(X) decltype(X), X
template<typename T,T t>
struct Foo
{ /* ... */ };
struct Bar {
int fun(float) {}
};
int main() {
Foo<TT(&Bar::fun)> f;
}
这将接受任何类型的非类型模板参数,如果Foo
实现仅适用于指向成员的指针,则可能会遇到难以理解的错误。
为了使它更安全一点,你需要一个告诉你类名的元函数:
template<typename T> struct member_ptr_traits;
template<typename Class,typename Ret,typename... Args>
struct member_ptr_traits<Ret (Class::*)(Args...)>
{
typedef Class class_type;
typedef Ret return_type;
};
#define TT(X) member_ptr_traits<decltype(X)>::class_type , X
template<typename T,int (T::*FUN)(float)>
struct Foo
{ /* ... */ };
struct Bar {
int fun(float) {}
};
int main() {
Foo<TT(&Bar::fun)> f;
}
这两个都使用C ++ 11,因此它们不能与旧的编译器一起使用。 这个简单的版本可以改写使用旧typeof
或类似的编译器扩展。 重写更安全的版本需要模拟可变参数模板。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.