Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Move or throw" using the ternary operator

Tags:

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;
}

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

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

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++?

like image 785
smancill Avatar asked Jul 02 '19 07:07

smancill


People also ask

How do you use a ternary operator?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.

What is ternary operator example?

Example: C Ternary Operator Here, age >= 18 - test condition that checks if input value is greater or equal to 18. printf("You can vote") - expression1 that is executed if condition is true. printf("You cannot vote") - expression2 that is executed if condition is false.

Can we use ternary operator in C++?

In C++, the ternary operator can be used to replace certain types of if...else statements. Negative Number! Here, both programs give the same output. However, the use of the ternary operator makes our code more readable and clean.

Which is faster if or ternary operator?

Moreover, as has been pointed out, at the byte code level there's really no difference between the ternary operator and if-then-else. As in the above example, the decision on which to choose is based wholly on readability.


1 Answers

This has to be a bug.

Either the move will be a move or the compilation should fail due to attempted copy of a unique_ptr (or a throw occurs in which case it doesn't matter).

q.get() == p.get() indeed shows that the internals have broken down, as this should not be possible.

I'd agree with cpplearner that this is bug 90393 (and all its dupes), which is reported as having been introduced in GCC 9.1.

Either downgrade, wait to upgrade, or reform your code into a nice if/else. 😊

like image 103
Lightness Races in Orbit Avatar answered Oct 23 '22 20:10

Lightness Races in Orbit