Reputation: 10466
With Visual C++ 2010, I have a class like this:
class MyClass{
public:
MyClass(){}
MyClass(MyClass &){/*...*/} //A
MyClass(const MyClass &){/*...*/} //B
template<typename T> MyClass(T &&t){ static_assert(
!std::is_same<typename
std::remove_cv<typename std::remove_reference<T>::type>::type,
MyClass>::value,
"Wrapping over wrapping is not allowed!"); } //C
};
int main(int, char**){
MyClass a;
const MyClass b(a); //assert fail if line A removed
auto c=b; //assert fail if line B removed
}
//If both A and B exists
//Warning C4521: multiple copy constructors specified
//Furthermore, if both A and B removed
//No error or warnings; VC2010 accepts peacefully.
//In debug mode you will find the compiler generated trivial copy constructor
According to C++ standard, both line A and B are considered copy constructors, and C is a convert constructor. It is not surprising that I receive a warning that I declared multiple copy constructors. However, if I remove any of them, the static_assert fails and the code would not compile, that means the template constructor received control.
I am sure that this behaviour follows the rule of function overloading. However is this a conflict of two rules? If A and B are copy constructors and one of them was declared, any attempt to copy the objects should not drop to the template, is it right?
Update: According to N3242, 12.8.7,
"a member function template is NEVER INSTANTIATED to perform the copy of a class object to an object of its class type."
the correct implementation should be:
Any comment?
Upvotes: 4
Views: 3278
Reputation: 507105
If A and B are copy constructors and one of them was declared, any attempt to copy the objects should not drop to the template, is it right?
A constructor that is not a copy constructor can still be used to copy objects. In your case the constructor instantiated from the constructor template is used for copying the object. Which is fine.
Upvotes: 0
Reputation: 4386
First of all, template<T>
should be template <typename T>
.
I am using gcc 4.4.3 on 64-bit Ubuntu Linux, the codes behave differently from what you have demonstrated in the post.
const MyClass b(a);
. The reason is that the object a is not constant, so constructor B can not be matched and the compiler has to instantiate the template constructor. Of course, const MyClass
and MyClass
are different types.is_same<MyClass&&, MyClass>::value
to be true. You may use typeid to print out both of the types.Upvotes: 1