У меня есть немного кода, который я считаю запутанным. В частности, когда я пытаюсь добавить что-то в список в качестве списка инициализаторов - он работает до тех пор, пока я не добавлю деструктор, - тогда он начинает пытаться найти конструктор копии.
Это не похоже на вполне последовательное поведение. Возьмите этот минимальный пример:
#include <list>
int main()
{
class MemberType
{
public:
MemberType() {}
MemberType(MemberType&& copy) { }
};
struct ListItemType
{
MemberType x;
~ListItemType() {}
};
std::list<ListItemType> myList;
myList.push_back({MemberType()});
return 0;
}
Это не скомпилируется в GCC и VS2015, потому что push_back
пытается получить доступ к конструктору копирования ListItemType
:
main()::ListItemType::ListItemType(const main()::ListItemType&)
(согласно моему пониманию). Это, по-видимому, имеет смысл, поскольку список push_back
сделает копию (так как нет конструктора перемещения), за исключением того, что это не поведение, если вы удалите деструктор. Прокомментируйте деструктор, и компиляция завершится успешно, как и ожидалось.
Тем не менее, нижеследующее прекрасно работает даже с деструктором - для его удовлетворения не нужны конструкторы копирования или перемещения. Это похоже на то же поведение для меня, хотя.
ListItemType foo = { MemberType() };
Наконец, если вы удалите или закомментируете конструктор перемещения MemberType
- компиляция снова завершится успешно, то есть следующее будет компилироваться.
#include <list>
int main()
{
class MemberType
{
public:
MemberType() {}
};
struct ListItemType
{
MemberType x;
~ListItemType() {}
};
std::list<ListItemType> myList;
myList.push_back({MemberType()});
return 0;
}
Может кто-нибудь объяснит здесь поведение? Почему push_back
пытается получить доступ к конструктору копирования ListItemType
- но только если ListItemType
имеет деструктор, а MemberType
имеет конструктор перемещения?