2017-09-08 63 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)工作。