为什么不使用我的(模板)构造函数进行初始化?

pap*_*nik 3 c++ templates constructor

为什么输出是0003212?

#include <iostream>
using namespace std;

template<typename X> class C
{
public:
    C() { cout<<"0";}
    template<class T> C(const C<T>& c) { cout<<"1";}
    C(const C<int>& c) { cout<<"2";}
    template<class T> C(const C<T*>& c) { cout<<"3";}
};

int main(int argc, char* args[])
{
    C<int> c1;          // 0
    C<double> c2;       // 0
    C<int*> c3;         // 0

    C<int> c4(c3);      // 3
    C<int> c5(c1);      // 2
    C<int> c6(c2);      // 1
    C<float> c7(c1);    // 2
    C<double> c8(c2);   // ?

    std::cin.get();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在最后一个含义行中调用了什么?

我可以假设这是一些自动创建的ctor,但无法弄清楚哪一个.

Ben*_*igt 5

这里有几个C++语言规则.

  1. 模板不能是复制构造函数.(标准规则12.8p2)

    一个非模板类的构造函数X是一个拷贝构造函数,如果它的第一个参数是类型X&,常量X&,volatile X&或者const volatile X&,并且或者有没有其他参数,否则所有其他参数默认参数.

  2. 如果未定义复制构造函数,则编译器将生成默认构造函数(如果可能).(标准规则12.8p7)

    如果类定义没有显式声明复制构造函数,则会隐式声明一个.如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数被定义为已删除; 否则,它被定义为默认值(8.4).如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况.因此,对于课程定义

    struct X {
       X(const X&, int);
    };
    
    Run Code Online (Sandbox Code Playgroud)

    隐式声明了复制构造函数.如果后来定义了用户声明的构造函数,X::X(const X& x, int i =0) { /? ... ?/ } 那么X由于模糊性,任何对复制构造函数的使用都是错误的; 无需诊断.

  3. 如果模板和非模板对于参数同样匹配,则非模板获胜.(标准规则13.3.3)规则是一个难以消化的大混乱,我只会展示重要的部分:

    [...]一个可行的函数F1被定义为比另一个可行的函数更好的函数,F2如果[...关于参数匹配的规则...],或者,如果不是,那么,F1是一个非模板函数,并且F2是一个函数模板专门化[...]

仅从您提供的代码中获取

C<int>::C(const C<int>&)
Run Code Online (Sandbox Code Playgroud)

是一个用户定义的复制构造函数,可以打印2.所有X比其他int没有定义拷贝构造函数,所以编译器创建一个.

也可以看看