Search code examples
c++constexprparameter-pack

affect of constexpr on Parameter pack


Why is this code invalid without constexpr:

template<typename ...Tpack>
auto CalculateSum(Tpack ...pack)
{
    if constexpr (sizeof...(Tpack) > 0)
    return (pack + ...);
    else
        return 0;
}

int main()
{
    std::cout << CalculateSum(2, 3, 4, 5, 7.5, 6) << '\n';
}

whereas if there are only int in the arguments, it gets valid.

Compiler says: 'auto' in return type deduced as 'int' here but deduced as 'double' in earlier return statement

But how does constexpr resolves?


Solution

  • The reason you need the if constexpr instead of a plain if is that you are trying to return two different types, which is not allowed with automatic return type deduction.

    With return (pack + ...); the return type is going to be double because one of your parameters is a double. On the other hand, return 0; is going to return an int. Since those type do not match, you get an error. You need to if constexpr to make either return (pack + ...); or return 0; be the only line of code that actually gets compiled, which leaves you with just a single type that the function could return.

    If you switch to using a trailing return type, you can get rid of the if constexpr and use a plain if like

    template<typename ...Tpack>
    auto CalculateSum(Tpack ...pack) -> decltype((pack + ...))
    {
        if (sizeof...(Tpack) > 0)
            return (pack + ...);
        else
            return {};
    }
    

    But that isn't DRY and is more typing, so I prefer the if constexpr version.