2017-09-08 104 views
2

我在理解C++ 17新功能的所有限制方面遇到了一些困難,該功能允許在構造函數上進行模板推導。具有部分專業化的類模板參數推導

特別地,該示例編譯正確:

struct B {}; 

template <typename T, typename = T> 
struct A { 
    A(T) {} 
}; 

int main() { 
    B b; 
    A a(b); // ok 
} 

雖然這一個不:

struct B {}; 

template <typename T, typename = T> 
struct A; 

template <typename T> 
struct A<T> { 
    A(T) {} 
}; 

int main() { 
    B b; 
    A a(b); // error 
} 

在該第二種情況下的錯誤是:

main.cpp: In function ‘int main()’: 
main.cpp:17:14: error: class template argument deduction failed: 
     A a(b); 
      ^
main.cpp:17:14: error: no matching function for call to ‘A(B&)’ 
main.cpp:4:12: note: candidate: template<class T, class> A(A<T, <template-parameter-1-2> >)-> A<T, <template-parameter-1-2> > 
    struct A; 
      ^
main.cpp:4:12: note: template argument deduction/substitution failed: 
main.cpp:17:14: note: ‘B’ is not derived from ‘A<T, <template-parameter-1-2> >’ 
     A a(b); 
      ^

這是爲什麼發生了什麼?

回答

4

類模板參數扣除僅考慮來自主類類模板的構造函數以便進行扣除。在第一個例子,我們有我們合成一個函數模板的一個構造函數:

template <class T> A<T> __f(T); 

__f(b)結果是A<B>,我們就大功告成了。

但在第二個例子中,主類模板就是:

template <typename T, typename = T> 
struct A; 

它沒有構造,所以我們沒有函數模板從他們合成。我們所擁有的是一個hypothetical default constructorcopy deduction guide,它們共同在此給我們重載集合:

template <class T> A<T> __f(); 
template <class T> A<T> __f(A<T>); 

這兩者都不是可行的__f(b)(你得到的編譯錯誤是關於設法匹配副本扣除指南),所以扣除失敗。


如果你想要這個成功,你必須寫一個演繹指南:

template <class T> 
A(T) -> A<T>; 

這將使A a(b)工作。