"Переместить или бросить" с помощью троичного оператора
Начиная с C++ 11 я использую троичный оператор для перемещения или броска в зависимости от некоторых условий, но с последним GCC (9.1 и транк) больше не работает.
Я уменьшил проблему до этого примера (постоянная ссылка Wandbox):
#include <iostream>
#include <memory>
int main()
{
auto p = std::make_unique<int>();
std::cout << "p.get(): " << p.get() << std::endl;
{
std::cout << "Move p into q" << std::endl;
auto q = p ? std::move(p) : throw std::invalid_argument{"null ptr"};
std::cout << "q.get(): " << q.get() << std::endl;
}
std::cout << "p.get(): " << p.get() << std::endl;
return 0;
}
Он работает с GCC 8.3 и старше, а также с каждой версией Clang; и p
перемещается:
p.get(): 0xde5c20
Move p into q
q.get(): 0xde5c20
p.get(): 0
Но теперь с GCC 9.1 и позже это не работает:
p.get(): 0x1d89150
Move p into q
q.get(): 0x1d89150
p.get(): 0x1d89150
И тогда программа вылетает из-за двойного освобождения.
Это ошибка в GCC 9.1/trunk? Или последний GCC - единственный, кто делает правильные вещи, и это недействительно C++?
Ответы
Ответ 1
Это должно быть ошибкой.
Либо этот шаг будет перемещением, либо компиляция должна завершиться неудачей из-за попытки копирования unique_ptr
(или в этом случае происходит throw
который не имеет значения).
q.get() == p.get()
действительно показывает, что внутренние q.get() == p.get()
сломались, поскольку это не должно быть возможным.
Я согласен с cpplearner, что это ошибка 90393 (и все ее ошибки), которая, как сообщается, была введена в GCC 9.1.