c++conditional-operatorlist-initializationtype-declaration

Why ternary operator cannot be used for this statement?


This code gives me compiler error: "expected an expression".

std::array< std::string, 3 > candidates = useOutname ? { "%O.log", "%O_.log", "_%O.log" } : { "%J.log", "%J_.log", "_%J.log" };

If change to plain if else statement, it works:

std::array< std::string, 3 > candidates;
if (useOutname) {
    candidates = { "%O.log", "%O_.log", "_%O.log" };
}
else {
    candidates = { "%J.log", "%J_.log", "_%J.log" };
}

I wonder why using ternary operator causes error here? Is it because of the curly bracket initialization?


Solution

  • The ternary operator (? : ) in C++ requires both the true and false branches to be expressions of same type. But { "%O.log", "%O_.log", "_%O.log" } is a braced-init-list, which is not an expression. It's a special syntax handled by copy-list-initialization. So, you cannot directly use brace-init-lists inside a ternary operator like this....

    If you really want a one-liner using the ternary operator, one option you can do is make both branches actual expressions of the same type, like:

    std::array<std::string, 3> candidates =
        useOutname
            ? std::array<std::string, 3>{ "%O.log", "%O_.log", "_%O.log" }
            : std::array<std::string, 3>{ "%J.log", "%J_.log", "_%J.log" };