具有部分特化的类模板参数推导

Sva*_*zen 2 c++ templates constructor template-argument-deduction c++17

我在理解新C++ 17功能的所有限制方面遇到了一些麻烦,该功能允许在构造函数上进行模板推导.

特别是,此示例正确编译:

struct B {};

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

int main() {
    B b;
    A a(b); // ok
}
Run Code Online (Sandbox Code Playgroud)

虽然这个没有:

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
}
Run Code Online (Sandbox Code Playgroud)

第二种情况的错误是:

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);
              ^
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

Bar*_*rry 6

类模板参数推导仅考虑类模板中的构造函数以进行推导.在第一个例子中,我们有一个构造函数,我们合成了一个函数模板:

template <class T> A<T> __f(T );
Run Code Online (Sandbox Code Playgroud)

结果__f(b)A<B>,我们已经完成了.

但在第二个示例中,主类模板只是:

template <typename T, typename = T>
struct A;
Run Code Online (Sandbox Code Playgroud)

它没有构造函数,因此我们没有函数模板可以从中进行合成.我们所拥有的只是一个假设的默认构造函数复制推导指南,它们共同为我们提供了这个重载集:

template <class T> A<T> __f();
template <class T> A<T> __f(A<T> );
Run Code Online (Sandbox Code Playgroud)

这两者都不可行__f(b)(你得到的编译错误是关于尝试匹配复制演绎指南),因此演绎失败.


如果你想要这个成功,你将不得不写一个演绎指南:

template <class T>
A(T ) -> A<T>;
Run Code Online (Sandbox Code Playgroud)

这将允许A a(b)工作.