2017-09-08 3 views
2

コンストラクタのテンプレート控除を可能にする新しいC++ 17機能のすべての制限を理解するのに問題があります。部分的な特殊化を伴うクラステンプレート引数の控除

特に

、この例では、正しくコンパイル:

struct B {}; 

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

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

この1つはない間:

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>であり、我々は行われている:最初の例では、我々は我々が関数テンプレートを合成する1つのコンストラクタを持っています。

しかし、第二の例では、主なクラステンプレートはちょうどです:

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

それは何のコンストラクタを持っていないので、我々は彼らから合成するいかなる関数テンプレートを持っていません。そう、(あなたが得るコンパイルエラーがコピー控除ガイドを一致しようとしている程度である)__f(b)ための実行可能であるどちらも

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

:私たちが持っているすべては、一緒に私たちは、このオーバーロード集合を与えるhypothetical default constructorcopy deduction guide、あります控除に失敗します。


あなたはこれが成功する場合は、控除ガイド記述する必要があります:A a(b)が動作できるようになる

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

を。

関連する問題