我正在编写一个函子F,它接受类型为void(* func)(T)和func的参数arg的函数.
template<typename T>
void F(void (*func)(T), WhatTypeHere? arg)
{
func(arg);
}
然后,仿函数F用arg调用func.我希望F不要复制arg,只是为了传递它作为参考.但后来我不能简单地写“void F(void(* func)(T),T&)”因为T可能是一个参考.所以我试着写一个特性,它允许得到适当的T参考类型:
T -> T&
T& -> T&
const T -> const T&
const T& -> const T&
我想出这样的事情:
template<typename T>
struct type_op
{
typedef T& valid_ref_type;
};
template<typename T>
struct type_op<T&>
{
typedef typename type_op<T>::valid_ref_type valid_ref_type;
};
template<typename T>
struct type_op<const T>
{
typedef const T& valid_ref_type;
};
template<typename T>
struct type_op<const T&>
{
typedef const T& valid_ref_type;
};
template<typename T>
void F(void (*func)(T), typename type_op<T>::valid_ref_type arg)
{
func(arg);
}
这不适用于例如
void a(int x) { std::cout << x << std::endl; }
F(&a, 7);
给出错误:
在传递’void F(void(*)(T),typename type_op :: valid_ref_type)的参数2中,从’int’类型的临时类型’int&’类型的非const引用无效初始化[with T = int] “
如何让这个特性发挥作用?
解决方法:
template<class T>
struct forwarding { typedef T const& type; };
template<class T>
struct forwarding<T&> { typedef T& type; };
template<typename T>
void F(void (*func)(T), typename forwarding<T>::type arg) {
func(arg);
}
void a(int x) { std::cout << x << std::endl; }
int main() {
F(&a, 7);
}
你的映射很接近,你实际上想要T映射到T const&太:
T -> T const& T& -> T& T const& -> T const&
请注意,参数类型为T const的函数的签名为T! const是一个实现细节:
void f(int const);
typedef void F(int); // typedef of function type
F* p = &f; // no error! f's signature doesn't include const