While looking for a example of binary tree implementation, I've noticed something strange in the code provided here . In Node structure's constructor a non-pointer type variable is assigned to a pointer type.
It compiles just fine (I'm using GCC 5.3.0). And what made me really confused is that compilation depends on other constructor's parameter, val .
It have no effect in class methods, only in constructors:
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;
}
};
The compilation error I'm getting is:
invalid constructor; you probably meant 'Test (const Test&)'
Why is that happening? Where in the standard is this behaviour described?
Your last constructor is a copy constructor . It's forbidden to have a copy constructor that passes its parameter by value, as otherwise you'd end up with infinite recursion.
The error you're getting is similar to
struct Foo
{
Foo(Foo);
};
More precisely, according to the standard:
12.8/2 Copying and moving class objects [class.copy]
A non-template constructor for class
X
is a copy constructor if its first parameter is of typeX&
,const X&
,volatile X&
orconst volatile X&
, and either there are no other parameters or else all other parameters have default arguments (8.3.6). [ Example:X::X(const X&)
andX::X(X&,int=1)
are copy constructors.
The others constructors/member functions seem ok because they are not instantiated, and the code is syntactically correct (in theory, Test<T>
may have a conversion operator to T*
for some specialization, and the compiler cannot check that before instantiation). However the copy constructor has to have a definite form, which is being enforced by the compiler.
All of your examples are invalid. You will get a compiler error when you try to instantiate any method:
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: In instantiation of 'void Test::testMethod(Test) [with T = int]': prog.cpp:16:18: required from here prog.cpp:9:23: error: cannot convert 'Test' to 'Test*' in assignment this->testPtr = notAPointer; ^
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.