Earth Engine
Earth Engine

Reputation: 10466

Multiple copy constructors specified

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

Answers (2)

Johannes Schaub - litb
Johannes Schaub - litb

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

Yun Huang
Yun Huang

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.

  • If nothing changed, the codes could be compiled without any warning. The constructor A and B are evoked one after another.
  • If I comment line A, it fails to be compiled just as what you said: failing in line 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.
  • However, if I comment line B only, the codes could be compiled successfully and the template copy constructor was evoked. Object b is a constant object, so construct A can not be matched and the compiler instantiate the template constructor. However, the question remains: should the static_assert fails or not? The difference may be because of the platform/compiler difference. GCC seems implementing the is_same<MyClass&&, MyClass>::value to be true. You may use typeid to print out both of the types.

Upvotes: 1

Related Questions