Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable default copy construct & assign constructor when using templated constructors

I'm trying to create a class which is copyable dependent on its template parameter (bool Copyable) otherwise it is move only.

It shall be constructible from the type itself (default constructor) through myclass(myclass&&) and myclass(myclass const&) when enabled through the template parameter bool Copyable.

Also it shall be constructible from myclass with other template arguments, which is covered by my current implementation through the templated constructors and assignment operators.

The rule of zero is used here to generate the default constructors and assignment operators through the inherited copyable helper struct which disables the copy constructor and copy assignment operator when bool Copyable is false.

template<bool>
struct copyable { };

template <>
struct copyable<false>
{
    // Disables copy construct & copy assign
    copyable() = default;
    copyable(copyable const&) = delete;
    copyable(copyable&&) = default;
    copyable& operator=(copyable const&) = delete;
    copyable& operator=(copyable&&) = default;
};

template<typename A, typename B, typename C>
struct storage_t
{
    // Implementation depends on A, B and C
};

template<typename A, typename B, typename C, bool Copyable>
class myclass
    : public copyable<Copyable>
{
    storage_t<A, B, C> _storage;

public:
    // It should generate the default constructors and
    // assignment operatos dependent on its inherited helper struct copyable.

    // Comment this out to disable the error...
    // (Implementation omitted)
    template<typename A, typename B, typename C>
    myclass(myclass<A, B, C, true> const&) { }

    template<typename A, typename B, typename C, bool Copyable>
    myclass(myclass<A, B, C, Copyable>&&) { }

    template<typename A, typename B, typename C>
    myclass& operator= (myclass<A, B, C, true> const&) { return *this; }

    template<typename A, typename B, typename C, bool Copyable>
    myclass& operator= (myclass<A, B, C, Copyable>&&) { return *this; }
    // ... comment end
};

By interpreting earlier answers at stackoverflow like:

  • Why does template copy constructor override default copy constructor?
  • Copy constructor of template class
  • Why can't I override the default copy constructor and assignment operator with template versions in C++

Which says:

The compiler will still generates a default copy-constructor for you, instead of instantiating the templated constructor.

I thought that the compiler still generates a default constrctor although there is a templated constructor provided.

But the compilation of the upper example code fails with the error message (msvc 2015):

error C2512: 'myclass': no appropriate default constructor available:

myclass<int, int, int, true> mc1;

When i outcomment the provided templated constructors and assignment operators the default constructors are used but the capability is lost to assign a myclass with other template parameters.

A simple usage example would be:

/////
// Testing the copyable class
myclass<int, int, int, true> mc1;

// Copy construct
myclass<int, int, int, true> mc2(mc1);
// Copy assign
mc1 = mc2;

/////
// Testing the move only class
myclass<int, int, int, false> mc3;

// Move construct
myclass<int, int, int, false> mc4(std::move(mc3));
// Move assign
mc3 = std::move(mc4);

// Not working part:
// Copy and move from myclass with other template params
myclass<int, int, float, true> mc5;
// Error here:
mc1 = mc5;

Is there a way to disable the copy construct and assignment operators as described through a template parameter and also provide templated constructors/assignment operators?

like image 645
Denis Blank Avatar asked Oct 30 '22 20:10

Denis Blank


1 Answers

Default constructor is not generated if you provide other constructors.

Just provide a default one:

myclass() = default;

In your case, copy constructor is still generated if possible (which is not the case, when you inherit of copyable<false>).

like image 143
Jarod42 Avatar answered Nov 15 '22 05:11

Jarod42