Ответ 1
Поведение, которое вы наблюдаете, генерируется правилами, определяющими, генерируются ли компилятором неявные экземпляры копирования или перемещения:
Неявное перемещение
Если не определено, конструктор перемещения неявно объявлен для класса if:
- класс не имеет определенных пользователем конструкторов копирования; и
- класс не имеет назначенного пользователем назначения копирования или переводит операторы присваивания; и
- класс не имеет определяемого пользователем деструктора.
Неявная копия
Если не определено, конструктор копирования неявно удален для класса, если:
- класс имеет определяемый пользователем конструктор перемещения; или
- другие причины, которые здесь не актуальны...
В вашем вопросе у вас есть несколько случаев:
Случай 1
-
ListItemType
имеет деструктор -
MemberType
имеет конструктор перемещения
Неявный конструктор перемещения для ListItemType
был удален из-за существования деструктора. Таким образом, push_back
должен использовать конструктор копирования, чтобы поместить ListItemType
в список.
В этом случае конструктор копирования для ListItemType
не может быть неявно объявлен как один из его членов данных (MemberType
) содержит конструктор перемещения, который предотвращает создание неявного конструктора копии для MemberType
.
Случай 2
-
ListItemType
не имеет деструктора -
MemberType
имеет конструктор перемещения
Конструктор перемещения может быть неявно сгенерирован для ListItemType
и используется для перемещения значения в список.
Случай 3
-
ListItemType
имеет деструктор -
MemberType
не имеет конструктора перемещения
Неявный конструктор копирования для ListItemType
и MemberType
может быть сгенерирован и использован для копирования значения в список.
Наконец, выражение ListItemType foo = { MemberType() };
является агрегатной инициализацией и следует различным правилам. В любом случае MemberType
будет иметь либо конструкцию перемещения, либо копию, достаточную для агрегатной инициализации.