编译器报告'已删除'operator =,但它就在那里

Aga*_*nju 1 c++ templates factory-method assignment-operator c++17

我遇到了一个讨厌的问题,编译器声称它operator=被删除了,但它就在那里.经过几个小时的尝试,我制作了一个最小的解决方案来重现这个问题.我正在使用MSVC Community Edition 2017 15.7.5(截至今天的最新版本,2018-07-20),并将其设置为'C++ 17'

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

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

"错误C2280:'C&C :: operator =(const C&)':尝试引用已删除的函数"

但第5行定义了这个运算符,右边是那些装饰器?

失败的赋值尝试将返回的值分配给const std::vector<C>&类成员变量.
我认为这const是产生问题,但删除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
  }
};
Run Code Online (Sandbox Code Playgroud)

完整错误文本:

------ 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 ==========
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 6

这是您问题的更短版本:

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
Run Code Online (Sandbox Code Playgroud)

虽然您确实默认了该功能,但这并不意味着它必然有效.它只是意味着你明确默认它.默认的复制赋值运算符将逐个复制 - 分配所有子对象和成员.但你的一个成员是const int,你不能复制 - 分配!是的const!

具体规则在[class.copy.assign]/7中:

如果X具有:[...]非const类型(或其数组)的非静态数据成员,或者[...] ,则类X的默认复制/移动赋值运算符被定义为已删除.

让会员公正int i,你没事.