Search code examples
c++templateslanguage-lawyerc++20constexpr

Using constant expressions as template parameter using a function parameter: which compiler is right?


I have this piece of code right there:

template <int V>
struct Constant {
    constexpr operator int() const noexcept { return V; }
};


template <class T, int N>
struct Array { };

auto function(auto s) -> Array<int, s + s> {
    return {};
}

auto const a = function(Constant<3>{});

To my greatest sadness, only Clang seems to accept this code.

Which compiler is right, and why?


Solution

  • I believe clang is correct here. Opened #114124 for gcc.

    Note that both gcc and MSVC accept this equivalent formulation:

    auto function(auto s) {
        return Array<int, s+s>{};
    }
    

    It's just that they don't allow the use of the parameter in the return type.

    But in the same way that writing s+s as a constant expression in the body of the function doesn't violate any rules of [expr.const]/5, no rules are violated in the trailing-return-type. We're just as much not reading anything (i.e. the usual reason such programs fail is because we're attempting an lvalue-to-rvalue conversion on a value not known to the constant evaluator), since the conversion function to int is constexpr and doesn't rely on any data.