https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118412

            Bug ID: 118412
           Summary: Non-conforming instantiation of definitions of scoped
                    member enum in class template
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: andre.brand at mailbox dot org
  Target Milestone: ---

The following standards-conforming (if my interpretation is correct, see below)
code is rejected by GCC but accepted by Clang and msvc: 


template <typename T>
struct S {
    enum class E1 : T { X = 0xFFFF };

    enum class E2 : int { X = 0xFFFF };
};

auto x = S<char>::E2::X;


For other kinds of members of the template class, GCC rightly accepts the
program because it does not eagerly instantiate their definitions.
For example, if you add the following members instead of E1, GCC accepts it:

template <typename T>
struct S {
    // [...]

    void MemberFunction() { constexpr T x = 0xFFFF; }

    static constexpr T StaticDataMember = 0xFFFF;

    struct MemberClass {
        static_assert(sizeof(T) == 42);
    };
}

Code and explanations are also here on Compiler Explorer:
https://godbolt.org/z/3WMWG7348

>From my interpretation, this should compile according to the C++ standard
because:

Quote from [temp.spec.general] https://wg21.link/temp.spec#temp.inst-3
"The implicit instantiation of a class template specialization causes 
the implicit instantiation of the declarations, but not of the definitions, 
of the non-deleted class member functions, member classes, 
scoped member enumerations, [...]"

And [dcl.enum] https://eel.is/c++draft/dcl.enum basically defines 
enumerator-definition as the stuff inside the curly braces.
So the implicit instantiation should not have instantiated the unused enum
class E2.


This is in fact a feature, and it is quite commonly used for member functions
like std::vector<T>::resize(size_t) if T is not default-constructible.
There are not as many good use cases for scoped member enumerations
but it's still an inconsistency with Clang and msvc (and with other kinds of
members).

Note: GCC versions 13.3 and 14.2 have the same issue.

Reply via email to