代码之家  ›  专栏  ›  技术社区  ›  Aganju

编译器报告'deleted'运算符=,但它在那里

  •  1
  • Aganju  · 技术社区  · 8 年前

    我遇到了一个棘手的问题,编译器声称 operator= 被删除了,但它在那里。经过几个小时的尝试,我找到了一个最小的解决方案,重现了这个问题。我正在使用MSVC Community Edition 2017 15.7.5(最新版本为2018-07-20),并已将其设置为“C++17”

    代码并非微不足道;其概念是,模板类TT用于强制静态成员函数的存在 foo 在一组班级里 Fn .这和 工厂模式 ,只是此解决方案不创建类实例,而是报告有关该类的静态详细信息。

    错误在最后一行的作业中报告,并读取(底部的完整错误列表):

    “错误C2280:'C&C::operator=(const C&)':试图引用 删除的功能“

    但是第五行定义了这个操作符,对吗?

    失败的分配尝试分配返回的 const std::vector<C>& 到类成员变量。
    我以为 const 正在制造问题,但删除了所有 康斯特 在每个功能中没有任何区别;同一行中有同样的错误。

    问题:为什么编译器会报告这个问题,可能的修复方法是什么?
    我想这一定是我错过的傻事,但我找不到。

    #include <vector>
    
    class C
    {
    public:
      C(int ii) : i(ii) {}
      C& operator=(const C&) = default;    /// HERE is the assignment operator
      const int i;
    };
    typedef std::vector<C> CVec;   // shorthand for a vector of C's
    
    template <class T>   // this template forces classes F1, F2, ... to have a static member function 'foo'
    class TT {
    public:
      static const CVec& foo(void) { return T::foo(); }
    };
    
    class F1  // one of many Fn classes
    {
    public:
      static const CVec& foo(void) { static CVec cv{ C{ 1 }, C{ 2 } }; return cv; }    // static member as forced by template
      //...
    };
    class F2  // another one of many Fn classes
    {
    public:
      static const CVec& foo(void) { static CVec cv{ C{ 3 } }; return cv; }     // static member as forced by template
      //...
    };
    
    class D    // controller class
    {
    public:
      CVec cv;
      const CVec& bar(int z)   // function to select one of the subclasses
      {
        switch (z)
        {
          case 1: return TT<F1>::foo();
          case 2: return TT<F2>::foo();
            //...
        }
      }
    
      void foobar(void)  //selector (from user input)
      {
        int z = 2; // user input
        cv = bar(z);   // THIS assignment produces the error
      }
    };
    

    错误全文:

    ------ Build started: Project: BG, Configuration: Debug Win32 ------
    bgcore.cpp
    c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\xutility(2443): error C2280: 'C &C::operator =(const C &)': attempting to reference a deleted function
    d:\projects\bg\core\bgcore.h(8): note: see declaration of 'C::operator ='
    c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\xutility(2462): note: see reference to function template instantiation '_OutIt std::_Copy_unchecked1<_InIt,_OutIt>(_InIt,_InIt,_OutIt,std::_General_ptr_iterator_tag)' being compiled
            with
            [
                _OutIt=C *,
                _InIt=C *
            ]
    c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\vector(1430): note: see reference to function template instantiation '_OutIt *std::_Copy_unchecked<_Iter,C*>(_InIt,_InIt,_OutIt)' being compiled
            with
            [
                _OutIt=C *,
                _Iter=C *,
                _InIt=C *
            ]
    c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\vector(1448): note: see reference to function template instantiation 'void std::vector<C,std::allocator<_Ty>>::_Assign_range<_Iter>(_Iter,_Iter,std::forward_iterator_tag)' being compiled
            with
            [
                _Ty=C,
                _Iter=C *
            ]
    c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\vector(1448): note: see reference to function template instantiation 'void std::vector<C,std::allocator<_Ty>>::_Assign_range<_Iter>(_Iter,_Iter,std::forward_iterator_tag)' being compiled
            with
            [
                _Ty=C,
                _Iter=C *
            ]
    c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\vector(1471): note: see reference to function template instantiation 'void std::vector<C,std::allocator<_Ty>>::assign<C*,void>(_Iter,_Iter)' being compiled
            with
            [
                _Ty=C,
                _Iter=C *
            ]
    c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\vector(1471): note: see reference to function template instantiation 'void std::vector<C,std::allocator<_Ty>>::assign<C*,void>(_Iter,_Iter)' being compiled
            with
            [
                _Ty=C,
                _Iter=C *
            ]
    c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\vector(1457): note: while compiling class template member function 'std::vector<C,std::allocator<_Ty>> &std::vector<_Ty,std::allocator<_Ty>>::operator =(const std::vector<_Ty,std::allocator<_Ty>> &)'
            with
            [
                _Ty=C
            ]
    d:\projects\bg\core\bgcore.h(49): note: see reference to function template instantiation 'std::vector<C,std::allocator<_Ty>> &std::vector<_Ty,std::allocator<_Ty>>::operator =(const std::vector<_Ty,std::allocator<_Ty>> &)' being compiled
            with
            [
                _Ty=C
            ]
    d:\projects\bg\core\bgcore.h(22): note: see reference to class template instantiation 'std::vector<C,std::allocator<_Ty>>' being compiled
            with
            [
                _Ty=C
            ]
    Done building project "BG.vcxproj" -- FAILED.
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
    
    2 回复  |  直到 8 年前
        1
  •  6
  •   Barry    8 年前

    以下是你的问题的简短版本:

    class C
    {
    public:
      C(int ii) : i(ii) {}
      C& operator=(const C&) = default;
      const int i;
    };
    
    C a(1);
    a = a; // error: use of deleted function
    

    而你呢 违约 函数,这并不意味着它一定有效。这只意味着你明确地默认了它。默认的复制指定操作符将逐个复制指定所有子对象和成员。但你的一个成员是 const int ,你不能复制它!它是 const !

    具体规定见附件 [class.copy.assign]/7 :

    如果X有以下情况,则类X的默认复制/移动分配运算符定义为已删除: [...] 的非静态数据成员 康斯特 非类类型(或其数组),或 [...]

    让会员公正 int i ,你很好。

        2
  •  0
  •   Caleth    8 年前

    你是 总是 允许 = default 一个特殊的成员函数。这有助于遵守规则 rule of zero or five 。它向读者清楚地表明,您已经考虑过该成员,并且想要默认行为。

    推荐文章