RamblingMad
RamblingMad

Reputation: 5518

overloaded constructor illegal with move and copy

I have a class that I'm writing that will take a special type for one of its constructors that could be any type that fits my requirements. I have run into the issue that this templated constructor causes my copy and move constructors to be illegal overloads!

My class is layed 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?

Upvotes: 3

Views: 95

Answers (2)

T.C.
T.C.

Reputation: 137425

Constrain it.

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

Depending on your particular use case, you may also want to constrain Special further to only types that fit your requirements.

Upvotes: 5

Jarod42
Jarod42

Reputation: 217810

This example shows the 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 has an exact match with your template constructor.

You may:

  • use SFINAE to forbid myclass& in the template (as in T.C's answer)
  • provide an other overload (with exact match):

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

    Demo

Upvotes: 0

Related Questions