"Move or throw" using the ternary operator

sma*_*ill 16 c++ gcc c++11

Since C++11 I have been using the ternary operator to move or throw based on some condition, but with latest GCC (9.1 and trunk) is not working anymore.

I have reduced the problem to this example (Wandbox permalink):

#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;
}
Run Code Online (Sandbox Code Playgroud)

It works with GCC 8.3 and older, and with every Clang version; and p is moved:

p.get(): 0xde5c20
Move p into q
q.get(): 0xde5c20
p.get(): 0
Run Code Online (Sandbox Code Playgroud)

But now with GCC 9.1 and later it doesn't work:

p.get(): 0x1d89150
Move p into q
q.get(): 0x1d89150
p.get(): 0x1d89150
Run Code Online (Sandbox Code Playgroud)

And then the program crashes due to a double free.

Is this a bug in GCC 9.1/trunk? Or latest GCC is the only one doing the right thing and this is not valid C++?

Lig*_*ica 3

一定是一个错误。

要么移动将是移动,要么编译因尝试复制 a 而失败unique_ptr(或者发生 a,throw在这种情况下并不重要)。

q.get() == p.get()确实表明内部已经损坏,因为这不应该是不可能的。

我同意 cpplearner 的观点,即这是bug 90393(及其所有的骗局),据报道该 bug 已在 GCC 9.1 中引入。

要么降级,等待升级,要么将代码改造成漂亮的if/ else.