Я столкнулся с неприятной проблемой, когда компилятор требует 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
}
};
Полный текст ошибки:
------ 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 ==========
Вот гораздо более короткая версия вашей проблемы:
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 имеет:
[…] нестатический член данныхconst
неклассный тип (или его массив), или
[…]
Сделайте участника просто int i
и ты в порядке.
Вы всегда разрешено = default
специальная функция-член. Это облегчает подчинение Правило ноль или пять. Это дает читателю понять, что вы рассмотрели этот элемент и хотите поведение по умолчанию.