2012-01-08 92 views
11

在C++ 03中,在某些上下文中不會發生模板參數推導。例如:模板別名如何影響模板參數推演?

template <typename T> struct B {}; 

template <typename T> 
struct A 
{ 
    typedef B<T> type; 
}; 

template <typename T> 
void f(typename A<T>::type); 

int main() 
{ 
    B<int> b; 
    f(b); // ERROR: no match 
} 

這裏,int不推導出T,因爲嵌套類型如A<T>::type是非推導出上下文。

如果我寫的函數是這樣的:

template <typename T> struct B {}; 

template <typename T> 
void f(B<T>); 

int main() 
{ 
    B<int> b; 
    f(b); 
} 

一切都很好,因爲B<T>一個推斷上下文。

但是,在C++ 11中,可以使用模板別名以類似於第二個示例的語法來僞裝嵌套類型。例如:

template <typename T> struct B {}; 

template <typename T> 
struct A 
{ 
    typedef B<T> type; 
}; 

template <typename T> 
using C = typename A<T>::type; 

template <typename T> 
void f(C<T>); 

int main() 
{ 
    B<int> b; 
    f(b); 
} 

在這種情況下,模板參數推導工作嗎?換句話說,模板別名是推斷的上下文還是非推斷的上下文?或者他們是否繼承了他們別名的推導/未推導的狀態?

+1

別名只是別名。這就像寫作'template void f(typename A :: type);',這是不可扣除的。 – 2012-01-08 03:43:19

+0

可能重複的[C++,模板參數不能被推斷](http://stackoverflow.com/questions/6060824/c-template-argument-can-not-be-deduced) – Nawaz 2012-01-08 03:43:46

+0

我認爲Kerrek SB是正確的對這個。如果提供了一個報價,我不需要去搜索一個;-) – 2012-01-08 03:45:57

回答

8

換言之,是模板別名一個推導出上下文還是非推測上下文?

它們可以像沒有使用模板別名的等效代碼一樣推導出來。例如

template<typename T> 
using ref = T&; 

template<typename T> 
void f(ref<T> r); 

現在,您可以撥打f(x)T將演繹完美的罰款。在f的定義時間,ref<T>被類型T&取代。並且T&是推斷的上下文。

在你的情況C<T>typename A<T>::type取代,這是T非推斷上下文中,因此T不能推斷。

+1

約翰內斯傑出答案中的關鍵詞是「在'f'的*定義時間*已經」(重點是我的)。很容易錯過,但知道它解釋了一切。 – 2012-09-24 00:06:10

1

想象一下:

template <typename T> struct Foo { typedef T type; } 
template <> struct Foo<char>  { typedef int type; } 

template <typename T> using mytype = typename Foo<T>::type; 

template <typename T> void f(mytype<T>); 

現在,如果我想int n; f(n);,我怎麼會決定我是否要T = intT = char?整個問題不受模板別名的影響,因爲你不能推導出所有可能定義某些東西的東西。

1

我認爲在C++標準相關報價14.5.7 [temp.alias]段2:

當模板id是指一個別名模板的專業化,它等同於通過將其模板參數替換爲別名模板的type-id中的模板參數而獲得的關聯類型。 [注意:別名模板名稱永遠不會被推斷出來。 - 結束註釋]

有一個例子在引用後有效地說明,在函數模板中使用別名模板並希望推斷模板參數是毫無意義的。這顯然適用於不涉及嵌套類型的情況。

+0

您上次的陳述不正確。你的扣減報價說的是別名模板名稱不能被推斷出來。這是'template