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.

Reply via email to