2010-04-13 29 views
3

我正在写一个函数functor F,它接受void(func)(T)和func的参数arg的函数。从trait获得const或非const引用类型

template<typename T> 
    void F(void (*func)(T), WhatTypeHere? arg) 
{ 
    func(arg); 
} 

然后functor 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); 

给错误:在通过参数2的类型从一个临时类型“INT”的“INT &”的非const引用 无效初始化'void F(void(*)(T),typename type_op :: valid_ref_type)[with T = int]'

如何让这个特征起作用?

+0

我认为这是非常相似的这一个:http://stackoverflow.com/questions/2539361/c-template-functor-cannot-deduce-reference-type – 2010-04-17 12:25:52

回答

5
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  -> T const& 
T&  -> T& 
T const& -> T const& 

需要注意的是为T常量的参数类型函数有T的签名!该常量是一个实现细节:

void f(int const); 
typedef void F(int); // typedef of function type 
F* p = &f; // no error! f's signature doesn't include const 
+0

绝对完美的解决方案。还修复了引用参数的调用:void a(int&x){std :: cout << x << std :: endl; } – maciekp 2010-04-13 10:45:57

2

所有你需要的是删除参考:

template<typename T> struct remove_reference { typedef T type; }; 
template<typename T> struct remove_reference<T&> { typedef T type; }; 

然后重新添加如下:

remove_reference<T>::type& 

你的函数应该声明如下:

template<typename T> 
void F(void (*func)(T), const typename remove_reference<T>::type& arg) 
{ 
    func(arg); 
} 
+1

与你的特质相同的错误:类型'int'的类型'int'的const引用。还传递const int&生成一个错误: const int&cri = 7; F(&a,cri); “类型'int&'的引用类型'const int'的引用无效初始化” – maciekp 2010-04-13 10:35:36

+0

@maciekp,已修复。 – 2010-04-13 10:38:36

+1

对不起,没有看到const。适合我! – maciekp 2010-04-13 10:39:13

1

这是在我的脑海里有点模糊,但我认为这种提升(也许是boost :: bind)通过仅提供const T&特性解决了这个问题s,并要求使用ref(x)来指示非const引用。

+0

不幸的是,我不允许使用提升。但你的回答肯定是正确的。 – maciekp 2010-04-13 10:37:15

相关问题