Я работаю над собственным умным указателем и столкнулся с некоторыми странными проблемами.Оператор назначения перемещения не вызывался.Поэтому я написал тестовый класс и смог воспроизвести проблему.Оператор назначения перемещения не вызывается, но происходит назначение копирования (даже когда нет оператора назначения копирования).
Это мой тестовый класс
#include <utility>
#include <iostream>
struct tag_t {};
constexpr tag_t tag {};
template <typename T>
struct Foo {
Foo() noexcept
: val{} {
std::cout << "Default construct\n";
}
template <typename U>
Foo(tag_t, const U &val) noexcept
: val{val} {
std::cout << "Construct " << val << '\n';
}
~Foo() noexcept {
std::cout << "Destruct " << val << '\n';
}
template <typename U>
Foo(Foo<U> &&other) noexcept
: val{std::exchange(other.val, U{})} {
std::cout << "Move construct " << val << '\n';
}
template <typename U>
Foo &operator=(Foo<U> &&other) noexcept {
std::cout << "Move assign " << other.val << '\n';
val = std::exchange(other.val, U{});
return *this;
}
T val;
};
Это тесты
int main() {
{
Foo<int> num;
std::cout << "Value " << num.val << '\n';
num = {tag, 5};
std::cout << "Value " << num.val << '\n';
}
std::cout << '\n';
{
Foo<int> num;
std::cout << "Value " << num.val << '\n';
num = Foo<int>{tag, 5};
std::cout << "Value " << num.val << '\n';
}
return 0;
}
После запуска тестов я получаю эти результаты
Default construct
Value 0
Construct 5
Destruct 5
Value 5
Destruct 5
Default construct
Value 0
Construct 5
Move assign 5
Destruct 0
Value 5
Destruct 5
Меня сбивает с толку вывод первого теста.Оператор назначения перемещения не вызывается, но выполняется назначение копирования.В результате 5
уничтожается дважды.Не идеально, когда вы пытаетесь сделать умный указатель!
Я компилирую с Apple Clang с отключенной оптимизацией.Может кто-нибудь объяснить мои наблюдения?Кроме того, как я могу убедиться, что оператор присваивания был вызван в первом тесте?