簡體   English   中英

如何使用引用使模板類型推導工作?

[英]How do I make template type deduction work with references?

我有一個模板函數, func

template<typename T>
void func(T p)  { f(p); }

還有一組函數f

f(SomeType&);
f(int);
...

如果我使用引用作為函數參數p實例化模板函數func ,而不顯式指定模板參數T ,那么推導出的類型將不是p的引用類型,而是類型pp的引用,例如:

SomeType s;
SomeType& ref_to_s = s;
func(ref_to_s);             // Type deduction results in: func<SomeType>(ref_to_s)
func<SomeType&>(ref_to_s);  // Need to explicitly specify type to work with reference

所以,我的問題是:

  • 為什么編譯器在上述情況下無法推斷引用類型SomeType&
  • 有沒有辦法定義模板函數func ,因此類型推導與引用類型一起工作,而沒有明確指定模板參數T

要清楚,我想要兩者兼顧(參見上面的函數f ):

func(ref_to_s);    // Calls func<SomeType&>(ref_to_s)
func(1);           // Calls func<int>(1)

第一部分的答案是從值初始化對象並將引用綁定到值被認為是同樣好的(兩者都是重載決策中的“完全匹配”),因此不推導出參數的引用。 相反,您必須准確指定它。 對於相關示例,請考慮假設的構造

T x = f();

其中T是(在這個思想實驗的持續時間)你應該推斷的東西。 x應該是什么 - 一個對象或一個引用? 它取決於什么? 當然,右邊的表達式有一個值,該值的類型始終是對象類型。 你應該如何決定? 您可以查詢表達式的值類別,但這太微妙了。 所以相反, 必須說出你想要的東西:

T x = f();    // x is an object
T & r = f();  // r is a reference

在C ++中,如果將T替換為auto ,則實際上可以使用此機制。 相同的規則適用於函數模板的模板參數推導。

現在就如何解決你的問題。 通常的習慣用法是讓函數模板始終采用引用,然后將參數轉發給內部調用:

template <typename T>
void func(T && t)
{
    f(std::forward<T>(t));
};

現在func的參數始終是任何特化中的引用(但是由於稱為“引用折疊”的奇怪規則,它可以是左值或右值引用),並且該值使用相同的值類別組轉發到f ,並且當func的原始參數是左值時, f上的這個重載決策允許選擇左值引用重載。

使用轉發參考:

template<typename T>
void func(T && p)    //notice &&
{ 
    f(std::forward<T>(p));  //notice std::forward
}

現在請在本網站上搜索轉發引用(或之前提到的通用引用 )以及std::forward以了解更多相關信息。

考慮以下示例:

template<typename T>
void f(T value, T& ref) {// fake swapping
T temp = ref;
ref = value;
value = temp;
}

當編譯器試圖推導出T的類型時,合理的做法是首先從“value”和“ref”中刪除可能的引用,這樣

int i = 1; 
int j = 2;
f(i, j);    //value of j becomes 1.
//up to here, value of i is still 1

否則,事情會變得很奇怪。 如果T被推導為T&,則f(i,j)的類型將等於f(int&,int &&)。 假設T &&崩潰到T&,那么它變成f(int&,int&)。 這完全違背了程序員的意圖。

暫無
暫無

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

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