[英]C++11 : How can I define a function that accept a universal reference of a specific type of object?
問題:我正在用C ++ 11開發程序。 我想編寫一個同時接受右值引用和左值引用的函數。 (即通用參考)。
以下函數接受通用參考參數:
template<class T> void function(T&& t){/*SNIP*/}
但是,它接受所有類型的參數。 它破壞了函數的類型安全性。 如果我希望它接受特定類型的參數,該怎么辦?
這是我能想到的解決方案:
void function(Class& t){/*SNIP*/}
void function(Class&& t){ function(t); }
但是,這很丑。 如果我想更改要接受的參數或更改函數名稱,則必須同時更新兩個版本的函數。 還有比這更好的了嗎?
編輯:問題解決了。 你們都回答得很好。 我對兩個答案都投了+1,以表示贊賞。 我將離開這個問題幾天。 投票最多的答案將被接受。
EDIT2:我最終得到以下代碼:
template < class T,
class=typename std::enable_if<std::is_same<Class, typename std::decay<T>::type>::value>::type //Dummy template parameter
>
void function(T&&){}
EDIT3:為此我編寫了一個宏定義:
#define uRefType(T, typeLimit) class T, class=typename std::enable_if<std::is_same<typename std::decay<T>::type, typeLimit>::value>::type
用法示例:
template< uRefType(T, Class) > void function(T&&){}
一種方法是使用std::enable_if
。 這是type_traits
標頭提供的結構。 如果布爾條件A
在編譯時評估為true,則定義使enable_if<A,B>::type
為類型B
否則為空。
因此,如果您有功能模板
template <typename T>
void fun(T &&)
{ /*...*/ }
並且要確保僅在T
是某種類型的情況下定義它,可以使用enable_if<...>::type
構造代替返回類型(此處為void
)。 然后將布爾條件A
定義為: T
是int
,類型B
定義為函數的原始返回類型(此處為void
)。
因此,如果我們希望僅在T
為int
時才定義fun
,則可以得到以下信息:
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_same<int,typename std::decay<T>::type>::value,void>::type
fun(T &&)
{ }
int main()
{
int lvali = 3;
double lvald = 3.3;
fun(3);
fun(lvali);
// fun(3.3); // this won't be accepted (not an int)
// fun(lvald) // this won't be accepted (not an int)
return 0;
}
請注意,布爾條件的定義方式如下(省略std::
以獲得更好的可讀性):
is_same<int,typename decay<T>::type>::value
使用decay
語句可確保無論T
是int
還是int &
(以及其他一些特殊情況),它都可以正常工作。
進一步說明:僅當所討論的函數的定義對於rvalue和lvalue相同時,這種技巧才真正有用。 在許多情況下,情況並非如此(因為右值大小寫將實現移動,左值大小寫將不會執行移動,或類似的操作)。
這兩個定義實際上都相同的典型情況是,函數體非常短,除了將參數轉發給另一個(可能是重載的)函數調用外,什么也沒有做:
template <typename T>
void fun(T &&obj)
{ other_fun(std::forward<T>(obj)); }
在那種情況下,最好不要使用任何enable_if
或其他技巧,因為other_fun
的聲明將確保最終僅接受某些類型。
將std::enable_if
與std::is_same
:
template<class T,
class = typename std::enable_if<std::is_same<float, T>::value>::type>
void function(T&& t){/*SNIP*/}
(正如在jogojapan的答案,我忘了提,第一說明)使用std::decay
的T
,因為T&
是不是同一類型的T
和const T
是不一樣的T`:
template<
class T,
class = typename std::enable_if<
std::is_same<float,
typename std::decay<T>::type>::value>::type>
void function(T&& t){/*SNIP*/}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.