«Переместить или бросить» с помощью троичного оператора - PullRequest
16 голосов
/ 02 июля 2019

Начиная с C ++ 11 я использую троичный оператор для перемещения или броска в зависимости от некоторых условий, но с последним GCC (9.1 и trunk) больше не работает.

Я уменьшил проблему доэтот пример ( Постоянная ссылка 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 Ответ

3 голосов
/ 02 июля 2019

Это имеет , чтобы быть ошибкой.

Либо это будет ход, либо компиляция не удастся из-за попытки скопировать unique_ptr (или throw в этом случае это не имеет значения).

q.get() == p.get() действительно показывает, что внутренние органы сломались, поскольку это не должно быть возможным.

Я бы согласился с cpplearner, что это ошибка 90393 (и все ее ошибки), о которых сообщается, что она была введена в GCC 9.1.

Либо понизьте версию, либо дождитесь обновления, либо преобразуйте ваш код в приятный if / else. ?

...