Search code examples
c++c++11ternary-operatoruniform-initialization

Uniform initialization with ternary operator return from function


I don't know if this is a compiler bug (gcc 4.8 on Arch Linux) or a problem with the standard, but the code below fails to compile. Why is getFoo1 allowed but not getFoo2?

struct Foo {
    int _i;
    Foo(int i):_i(i) { }
};

Foo getFoo1(int i) {
    if(i == 3) {
        return { i + 2 };
    } else {
        return { i };
    }
}

Foo getFoo2(int i) {
    return i == 3 ? { i + 2 } : { i };
}

int main() {
    auto foo1 = getFoo1(3); //fine
    auto foo2 = getFoo2(3); //oops
    return 0;
}

Solution

  • Braces per se do not form expressions (although all the elements of the initializer list are expressions). A braced-init-list is just a language construct that can be used for initialization in the contexts specified by § 8.5.4 of the C++11 Standard (including return statements).

    If you want your return statement to compile and still make use of the ternary operator and of list initialization, you have to rewrite it this way:

    return { i == 3 ? i + 2 : i };
    

    Notice, however, that the above is not necessary. As mentioned by David Rodriguez - dribeas in the comments), you could just give up using list initialization. This would work equally well:

    return i == 3 ? i + 2 : i;