Search code examples
c++visual-c++referencestaticconstinit

inconsistency between compilers when getting a `constinit` reference on a template parameter object


In a previous post I discussed a technic to create static values from non-type template parameters.

In this post and its accepted answer, a code was given to achieve this goal but it fails to compile in some cases with msvc.

A minimal example is given below:

#include <type_traits>

template <class T>
struct value_holder {
    T value;
};

template <auto V>
constexpr auto const& make_static() {
    if constexpr (std::is_class_v<decltype(V)>) {
        return V;
    } else {
        return make_static<value_holder{V}>().value;
    }
}

int main() {
    [[maybe_unused]] constinit static const auto v = make_static<2>();
    [[maybe_unused]] constinit static const auto& r = make_static<2>();

    return v;
}

LIVE

while gcc and clang accept this code, msvc output is:

error C2127: 'r': illegal initialization of 'constinit' entity with a non-constant expression

The behavior is the same up to msvc 19.40.

Is this a msvc bug?


Solution

  • This is an MSVC bug.

    [expr.const]p14:

    A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression [...] An entity is a permitted result of a constant expression if it is an object with static storage duration

    [temp.param]p8:

    An id-expression naming a non-type template-parameter of class type T denotes a static storage duration object of type const T, known as a template parameter object

    This seems to be a bug with constinit references specifically. As a workaround, use pointers instead.