2010-04-13 93 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