考虑一下代码:
class Character
{
void kill();
void send_to_wall();
}
template <typename T>
void GeorgeFunc(T fp)
{
??? obj;
(obj.*fp)();
}
int main()
{
GeorgeFunc(&Character::kill);
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:我怎么能得到????似乎编译器在模板实例化期间肯定知道这个类型是什么(Character),但我不知道如何得到它.我目前的解决方法是更改为:void GeorgeFunc(void (T::*fp)()),但从成员函数指针中获取类型会更简洁. decltype(fp)会回来void(Character::*)(),并decltype(fp())会回来void.有Character什么方法可以得到?
cdh*_*wie 15
Yes, just use a trait to determine this.
template <typename> struct member_function_traits;
template <typename Return, typename Object, typename... Args>
struct member_function_traits<Return (Object::*)(Args...)>
{
typedef Return return_type;
typedef Object instance_type;
typedef Object & instance_reference;
// Can mess with Args... if you need to, for example:
static constexpr size_t argument_count = sizeof...(Args);
};
// If you intend to support const member functions you need another specialization.
template <typename Return, typename Object, typename... Args>
struct member_function_traits<Return (Object::*)(Args...) const>
{
typedef Return return_type;
typedef Object instance_type;
typedef Object const & instance_reference;
// Can mess with Args... if you need to, for example:
static constexpr size_t argument_count = sizeof...(Args);
};
Run Code Online (Sandbox Code Playgroud)
Now your declaration is:
typename member_function_traits<T>::instance_type obj;
Run Code Online (Sandbox Code Playgroud)
However, I would argue that since you require a member function pointer (other types would fail to instantiate due to the line (obj.*fp)()1) that your function should take a member function pointer directly instead of a completely generic type.
So this definition would not only work, but I would consider it preferred -- the error messages when someone uses something other than a pointer-to-member-function will be much clearer because the argument type will be incompatible:
template <typename Return, typename Object>
void GeorgeFunc(Return (Object::*fp)())
{
Object obj;
(obj.*fp)();
}
Run Code Online (Sandbox Code Playgroud)
Note that this does allow passing a pointer-to-member-function that returns any type. Since we don't really use the return value, we don't care what it is. There is no reason to enforce that it is void as in your "workaround."
The only downside to using this approach is that you need two overloads if you intend to also accept pointers to member functions that are declared const. The completely generic implementation does not have this limitation. (I've long wished that pointers to const member functions were implicitly convertible to pointers to non-const member functions, but this is currently not allowed by C++.)
1这不是100%真实.如果您现在使用完全通用类型,那么调用者理论上可以传递成员数据指针而不是成员函数指针. obj.*fp将评估为对数据成员的引用,然后您将调用operator()()它.只要数据成员的类型实现了此运算符,GeorgeFunc就可以实例化模板函数.