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

标签 c++ templates constructor c++17 template-argument-deduction

我在理解允许对构造函数进行模板推导的新 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);
              ^

为什么会这样?

最佳答案

类模板参数推导只考虑来自primary 类模板的构造函数来进行推导。在第一个示例中,我们有一个构造函数,我们为其合成了一个函数模板:

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)去工作。

关于c++ - 具有部分特化的类模板参数推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46118787/

相关文章:

c++ - binutils和gcc有什么关系?

c++ - 为什么以下模板声明格式错误?

javascript - 原型(prototype)继承如何节省内存?

c++ - 打印所有可能的结果 C++?

c++ - 在 C++ 代码 gdb 中回溯指针

c++ - 如何分析 C/C++ 应用程序中内存访问所花费的时间?

c++ - 派生类中的函数模板特化

c++ - 使用声明来表示模板声明中的类型

Java 构造函数基础知识 : objects and fields with no current value

c# - 分离 C# 构造函数的前基和后基或链式构造函数调用指令