簡體   English   中英

C ++ 11:如何定義一個接受特定類型對象的通用引用的函數?

[英]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定義為: Tint ,類型B定義為函數的原始返回類型(此處為void )。

因此,如果我們希望僅在Tint時才定義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語句可確保無論Tint還是int & (以及其他一些特殊情況),它都可以正常工作。


進一步說明:僅當所討論的函數的定義對於rvalue和lvalue相同時,這種技巧才真正有用。 在許多情況下,情況並非如此(因為右值大小寫將實現移動,左值大小寫將不會執行移動,或類似的操作)。

這兩個定義實際上都相同的典型情況是,函數體非常短,除了將參數轉發給另一個(可能是重載的)函數調用外,什么也沒有做:

template <typename T>
void fun(T &&obj)
{ other_fun(std::forward<T>(obj)); }

在那種情況下,最好不要使用任何enable_if或其他技巧,因為other_fun的聲明將確保最終僅接受某些類型。

std::enable_ifstd::is_same

template<class T, 
         class = typename std::enable_if<std::is_same<float, T>::value>::type>
void function(T&& t){/*SNIP*/}

(正如在jogojapan的答案,我忘了提,第一說明)使用std::decayT ,因為T&是不是同一類型的Tconst 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*/}

參見http://ideone.com/ztkHsf上的演示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM