https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89367
Bug ID: 89367 Summary: Constexpr expression is not constexpr in template, but is constexpr in non-template. Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: frank.secilia at gmail dot com Target Milestone: --- Created attachment 45737 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45737&action=edit minimal preprocessed test case Morning, folks! I'm trying to make compile-time type ids. It's based on the fact that per-type static instances have unique addresses. I'm using those addresses as the type id. Originally, I figured this wouldn't work because taking the address of something couldn't be constexpr, but the address of a variable is known at compile time, so I gave it a try. g++ accepts it for a non-template type, but not if the type is a template. Attached is a preprocessed minimal test case, but here is something slightly more verbose with a few comments: // Concrete type with unique, per-type constexpr id. struct type_1 { static constexpr char const unique_address{}; static constexpr void const* const id{&unique_address}; }; constexpr char const type_1::unique_address; constexpr void const* const type_1::id; // Another concrete type with same. struct type_2 { static constexpr char const unique_address{}; static constexpr void const* const id{&unique_address}; }; constexpr char const type_2::unique_address; constexpr void const* const type_2::id; // Types have different ids and these evaluate at compile time, as expected. static_assert(type_1::id != type_2::id); // Same, but in a template. template <typename wrapped> struct type_id { static constexpr char const unique_address{}; static constexpr void const* const id{&unique_address}; }; template <typename wrapped> constexpr char const type_id<wrapped>::unique_address; template <typename wrapped> constexpr void const* const type_id<wrapped>::id; // This does not compile. static_assert(type_id<int>::id != type_id<float>::id); The reasons I think this is a bug is because the only difference between the succeeding and failing case is that the failing case is templated, and because this works on clang. I posted about this on stack overflow here https://stackoverflow.com/questions/43955536/constexpr-unique-id-compiles-with-clang-but-not-with-gcc. The simpler example at the bottom is missing a const on the out-of-line definitions, but the behavior is the same with or without them.