C ++,将非指针类型赋值给模板类的成员指针

时间:2016-02-13 16:07:36

标签: c++ templates pointers constructor member

在寻找二叉树实现的示例时,我注意到提供的代码here中有些奇怪。在 Node 结构的构造函数中,非指针类型变量被赋值给指针类型。

它编译得很好(我正在使用GCC 5.3.0)。让我感到困惑的是编译依赖于其他构造函数的参数 val

它对类方法没有影响,只在构造函数中有效:

template <typename T>
class Test {
    Test* testPtr;

    void testMethod(T t, Test<T> notAPointer) { // OK
        this->testPtr = notAPointer;
    }

    void testMethod(Test<T> notAPointer) {      // OK
        this->testPtr = notAPointer;
    }

    Test(T t, Test<T> notAPointer) {            // OK
        this->testPtr = notAPointer;
    }

    Test(Test<T> notAPointer) {                 // compilation error
        this->testPtr = notAPointer;
    }
};

我得到的编译错误是:

  

无效的构造函数;你可能意味着'测试(const测试&amp;)'

为什么会这样?标准中的这种行为描述在哪里?

2 个答案:

答案 0 :(得分:3)

您的上一个构造函数是copy constructor。禁止有一个复制构造函数按值传递它的参数,否则你最终会得到无限递归。

您获得的错误类似于

struct Foo
{
    Foo(Foo);
};

Live on Coliru

更确切地说,根据标准:

12.8 / 2复制和移动类对象[class.copy]

  

如果第一个参数的类型为XX&const X&volatile X&,则类const volatile X&的非模板构造函数是一个复制构造函数,并且没有其他参数,或者所有其他参数都有默认参数(8.3.6)。 [例如:X::X(const X&)X::X(X&,int=1)是复制构造函数。

其他构造函数/成员函数似乎没问题,因为它们没有实例化,并且代码在语法上是正确的(理论上,Test<T>可能有一个转换运算符T*用于某些特化,并且编译器在实例化之前无法检查)。但是,复制构造函数必须具有明确的形式,由编译器强制执行。

答案 1 :(得分:1)

您的所有示例均无效。当您尝试实例化任何方法时,您将收到编译器错误:

template <typename T>
struct Test {
    Test* testPtr;

    void testMethod(Test<T> notAPointer) {
        this->testPtr = notAPointer;
    }
};

int main() {
    Test<int> t1, t2;
    t1.testMethod(t2); // This line will cause the error.

    return 0;
}
  

prog.cpp:实例化'void Test :: testMethod(Test)[with   T = int]':prog.cpp:16:18:从这里需要prog.cpp:9:23:错误:   无法在分配中将“测试”转换为“测试*”            this-&gt; testPtr = notAPointer;                          ^