Почему следующий код работает, хотя я явно удалил move конструктор?
class X {
public:
X() = default;
X(const X&) = delete;
X(X&&) = delete;
int val = 42;
};
template<typename T>
int foo(T x) {
return x.val;
}
int main() {
X x1;
//X x2{x1}; // error
//X x3{std::move(x1)}; // error
//foo(x1); // error
//foo(std::move(x1)); //error
foo(X{}); // OK?
}
Какие ограничения налагаются на тип T кроме того, что он должен иметь member val, приводимый к int? Можно ли запретить последнюю передачу?
Потому что в строчке foo(X{}); нет ни копирования, ни перемещения. Есть материализация prvalue в объект с именем x. Материализация, как может быть понятно из самого термина, это прямое создание объекта из prvalue, без каких либо промежуточных копирований/перемещений. Запретить это нельзя, это «вшито» в стандарт C++17.
Подробнее я писал об этом здесь.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей