Overloaded constructor illegal with move and copy

I have a class that I am writing that will use a custom type for one of its constructors, which can be any type that suits my requirements. I ran into the problem that this templated constructor is forcing my constructors to copy and move as illegal overloads!

My class is laid out like this:

template<typename ... Types>
class myclass{
    public:
        myclass(const myclass &other){/* copy constructor */}
        myclass(myclass &&other){/* move constructor */}

        template<typename Special>
        myclass(Special &&arg){/* stops copy/move implementations */}
}

      

How can I get around this limitation?

+3


source to share


2 answers


Limit it.

template<typename Special,
         std::enable_if_t<!std::is_same<std::decay_t<Special>, myclass>{}, int> = 0 >
myclass(Special &&arg) { /* ... */ }

      



Depending on your specific use case, you can also restrict Special

further to only the type that suits your requirements.

+5


source


This example shows different cases:

const myclass c1(42);      // special: int
myclass c2(c1);            // copy
myclass c3(c2);            // special: myclass& (non const)
myclass c4(std::move(c3)); // move

      

Live Demo



your copy / move constructors are still legal overloads, but non const l-value matches exactly with your template constructor.

You can:

  • use SFINAE to disallow myclass&

    in the template (as in TC's answer)
  • provide another overload (with an exact match):

    myclass(myclass &other) : myclass(static_cast<const myclass &>(other)) {}
    
          

    Demo

0


source







All Articles