c++c++20conditional-operatorternarystdtuple

C++20 return a tuple in ternary statement


I have a small function that returns three values. I use a std::tuple to facilitate returning of multiple values.

What the function returns is determined by one variable, if the variable is not zero it returns one tuple, else it returns another one. Because I use C++20 I just use curly brackets ({}) to build the tuples.

I think using a ternary statement would be perfect, but the following doesn't work:

#include <tuple>

using std::tuple;

double hue(double b, double g, double r, double d, double i);

tuple<double, double, double> HSL_pixel(double b, double g, double r, double i, double x, double z) {
    double s = x + z;
    double d = z - x;
    double avg = s / 2;
    return d ? {hue(b, g, r, d, i), d / (1 - abs(s - 1)), avg} : {0.0, 0.0, avg};
}

In Visual Studio 2022, an error is detected at the first opening curly bracket position, it says: "expected an expression".

Changing to if else statement fixed the problem:

tuple<double, double, double> HSL_pixel(double b, double g, double r, double i, double x, double z) {
    double s = x + z;
    double d = z - x;
    double avg = s / 2;
    if (d) {
        return { hue(b, g, r, d, i), d / (1 - abs(s - 1)), avg };
    } 
    else {
        return { 0.0, 0.0, avg };
    }
}

But I want to use ternary. How can I use ternary in this case?


Solution

  • Grammatically, you cannot use a braced-init-list with the conditional operator. So just this is ill-formed:

    int a = true ? 1 : {};
    

    You have to write this instead:

    int b = true ? 1 : int{};
    

    Which in your example that's:

    cond ? tuple{a, b, c} : tuple{d, e, f}
    

    instead of:

    cond ? {a, b, c} : {d, e, f}
    

    Or, if you really prefer to use braced-init-list, then you'll have to use if/else (or just if). Just a style choice at that point.