模板中定义的副本分配运算符被编译器删除

Eos Pengwern

我熟悉的原则(例如,从这个答案这一个),当一个类有一个移动构造函数和/或移动赋值操作符,其默认的拷贝构造函数和拷贝赋值运算符将被删除。但是,在我看到的示例中,可以通过显式定义新的副本构造函数和赋值运算符来解决此问题。

在我的特定情况下,我有一个类,该类是从C样式结构和模板类的联合继承派生的。复制和移动分配运算符在模板中显式定义,而复制和移动构造函数在类本身中显式定义。换句话说,所有内容都是明确定义的,尽管不是全部都在同一位置这是一些示例代码:

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;
}

在Windows上的Visual C ++和Intel C ++中,这完全可以按照我的预期工作。但是,在Linux上的gcc 4.9.0上,我得到了可怕的错误消息:

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>

可以肯定的是,如果我在类本身而不是模板中定义一个显式的复制赋值运算符,该错误就会消失,但是这样做很麻烦,并且削弱了使用模板的优势,因为(a)我实际的复制赋值运算符是比这里显示的要大得多,并且(b)有许多不同的类都共享此模板。

那么,这仅仅是gcc 4.9.0中的一个bug,还是事实上标准所说的会发生?

乔纳森·韦克利

GCC是正确的(Clang和EDG同意)。

myTemplate 具有用户声明的move构造函数,因此将其副本分配运算符删除。

您提供了一个复制构造函数,但没有提供复制赋值运算符。只需声明一个复制赋值运算符myTemplate并将其定义为默认值即可。这需要多一行代码。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

模板化副本分配运算符

来自分类Dev

重载副本分配运算符

来自分类Dev

C ++从重载的副本分配运算符中调用默认的副本分配运算符

来自分类Dev

非类型模板结构的成员结构的重载副本分配运算符

来自分类Dev

删除副本分配运算符的VS 2015 Update 3错误

来自分类Dev

为什么std :: reference_wrapper显式定义副本分配运算符?

来自分类Dev

副本分配运算符何时调用?

来自分类Dev

转换运算符的离线定义的编译器差异

来自分类Dev

内部编译器错误-开关表达式中的模板化转换运算符

来自分类Dev

如何在副本分配运算符中访问私有变量?

来自分类Dev

如何使用Gnu编译器在VxWorks 7中重载新/删除运算符

来自分类Dev

为什么引用类型成员导致隐式声明的副本分配运算符被删除

来自分类Dev

编译器如何知道使用哪个运算符或函数分配了哪个内存?

来自分类Dev

Clang vs GCC vs MSVC模板转换运算符-哪个编译器正确?

来自分类Dev

重载的运算符=返回void是否不可能是副本分配运算符?

来自分类Dev

有没有正当理由不从副本分配运算符返回* this?

来自分类Dev

为什么我的副本分配运算符从未调用过?

来自分类Dev

如何避免副本分配运算符出现双重释放或损坏(快捷方式)?

来自分类Dev

编译器如何调用运算符转换?

来自分类Dev

强制编译器选择const运算符重载

来自分类Dev

编译器如何调用运算符转换?

来自分类Dev

补码运算符引起的编译器错误

来自分类Dev

编译器调用复制运算符而不是移动运算符

来自分类Dev

为什么在复制分配运算符的定义中需要删除?

来自分类Dev

C ++-模板中的复制分配运算符

来自分类Dev

为什么删除模板副本构造函数会导致赋值运算符无法工作?

来自分类Dev

为什么删除模板副本构造函数会导致赋值运算符无法工作?

来自分类Dev

使用模板分配运算符

来自分类Dev

继承的模板分配运算符

Related 相关文章

  1. 1

    模板化副本分配运算符

  2. 2

    重载副本分配运算符

  3. 3

    C ++从重载的副本分配运算符中调用默认的副本分配运算符

  4. 4

    非类型模板结构的成员结构的重载副本分配运算符

  5. 5

    删除副本分配运算符的VS 2015 Update 3错误

  6. 6

    为什么std :: reference_wrapper显式定义副本分配运算符?

  7. 7

    副本分配运算符何时调用?

  8. 8

    转换运算符的离线定义的编译器差异

  9. 9

    内部编译器错误-开关表达式中的模板化转换运算符

  10. 10

    如何在副本分配运算符中访问私有变量?

  11. 11

    如何使用Gnu编译器在VxWorks 7中重载新/删除运算符

  12. 12

    为什么引用类型成员导致隐式声明的副本分配运算符被删除

  13. 13

    编译器如何知道使用哪个运算符或函数分配了哪个内存?

  14. 14

    Clang vs GCC vs MSVC模板转换运算符-哪个编译器正确?

  15. 15

    重载的运算符=返回void是否不可能是副本分配运算符?

  16. 16

    有没有正当理由不从副本分配运算符返回* this?

  17. 17

    为什么我的副本分配运算符从未调用过?

  18. 18

    如何避免副本分配运算符出现双重释放或损坏(快捷方式)?

  19. 19

    编译器如何调用运算符转换?

  20. 20

    强制编译器选择const运算符重载

  21. 21

    编译器如何调用运算符转换?

  22. 22

    补码运算符引起的编译器错误

  23. 23

    编译器调用复制运算符而不是移动运算符

  24. 24

    为什么在复制分配运算符的定义中需要删除?

  25. 25

    C ++-模板中的复制分配运算符

  26. 26

    为什么删除模板副本构造函数会导致赋值运算符无法工作?

  27. 27

    为什么删除模板副本构造函数会导致赋值运算符无法工作?

  28. 28

    使用模板分配运算符

  29. 29

    继承的模板分配运算符

热门标签

归档