Copy assignment operator defined in template being deleted by compiler

一世执手 提交于 2019-12-13 16:02:44

问题


I'm familiar with the principle (for example, from this answer and this one) that when a class has a move constructor and/or move assignment operator, its default copy constructor and copy assignment operator are deleted. However, In the examples I've seen, this can be addressed by explicitly defining a new copy constructor and assignment operator.

In my particular case, I have a class which is derived by joint inheritance from a C-style struct and a template class. The copy and move assignment operators are explicitly defined in the template, whilst the copy and move constructors are explicitly defined in the class itself. In other words, everything is defined explicitly, though not all in the same place. Here is some example code:

typedef struct {
    int n;
} myStruct;

template <typename T> class myTemplate
{
public:
    // Default constructor
    myTemplate<T>() : t_n(nullptr) {}

    // Cannot create copy or move constructors in template, as cannot 
    // access the 'n' member directly

    // Copy assignment operator
    myTemplate<T> & operator=(const myTemplate<T> &source)
    {
        if (this != &source)
        {
            *t_n = *(source.t_n);
        }
        return *this;
    }

    //! Move assignment operator
    myTemplate<T> & operator=(myTemplate<T> &&source)
    {
        if (this != &source)
        {
            *t_n = *(source.t_n);
            *(source.t_n) = 0;
            source.t_n = nullptr;
        }
        return *this;
    }

    T* t_n;
};

class myClass : public myStruct, public myTemplate<int>
{
public:
    // Default constructor
    myClass() : myTemplate<int>()
    {
        n = 0;
        t_n = &n;
    }

    // Alternative constructor
    myClass(const int &n_init) : myTemplate<int>()
    {
        n = n_init;
        t_n = &n;
    }

    // Copy constructor
    myClass(const myClass &source) : myTemplate<int>()
    {
        n = source.n;
        t_n = &n;
    }

    // Move constructor
    myClass(myClass &&source) : myTemplate<int>()
    {
        n = source.n;
        t_n = &n;
        source.n = 0;
        source.t_n = nullptr;
    }
};

int main()
{

    myClass myObject(5);
    myClass myOtherObject;

    // Compilation error here:
    myOtherObject = myObject;

    return 1;
}

In Visual C++ and Intel C++ on Windows, this works exactly as I'd expect it to. On gcc 4.9.0 in Linux, however, I get the dreaded error message:

g++ -c -std=c++11 Main.cppMain.cpp: In function ‘int main()’:
Main.cpp:78:19: error: use of deleted function ‘myClass& myClass::operator=(const myClass&)’
     myOtherObject = myObject;
               ^
Main.cpp:39:7: note: ‘myClass& myClass::operator=(const myClass&)’ is implicitly declared as deleted because ‘myClass’ declares a move constructor or move assignment operator
 class myClass : public myStruct, public myTemplate<int>

Sure enough, the error goes away if I define an explicit copy assignment operator in the class itself, rather than in the template, but that's bothersome to do and undermines the advantage of using the template, since (a) my actual copy assignment operator is a lot bigger than the one shown here and (b) there are a large number of different classes that all share this template.

So, is this simply a bug in gcc 4.9.0, or is this in fact what the standard says should happen?


回答1:


GCC is correct (and Clang and EDG agree).

myTemplate has a user-declared move constructor, therefore its copy assignment operator is deleted.

You've provided a copy constructor, but not copy assignment operator. Just declare a copy assignment operator for myTemplate and define it as defaulted. That takes one extra line of code.



来源:https://stackoverflow.com/questions/25246573/copy-assignment-operator-defined-in-template-being-deleted-by-compiler

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!