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;
}
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?
This is an MSVC bug.
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
An id-expression naming a non-type template-parameter of class type
T
denotes a static storage duration object of typeconst T
, known as a template parameter object
This seems to be a bug with constinit
references specifically. As a workaround, use pointers instead.