8

I know that, generally, we can forward-declare enums in C++11.

So, why does this:

enum kind_t { kind1, kind2 };

template <kind_t Kind> struct foo {};

template <> struct foo<kind1> {
    enum named : int;
};

enum foo<kind1>::named : int {
    named1 = 123,
    named2 = 456,
};

fail to compile with GCC (12.1)? The error is (Godbolt):

<source>:9:6: error: cannot add an enumerator list to a template instantiation
    9 | enum foo<kind1>::named : int {
      |      ^~~~~~~~~~
ASM generation compiler returned: 1
<source>:9:6: error: cannot add an enumerator list to a template instantiation
    9 | enum foo<kind1>::named : int {
      |      ^~~~~~~~~~

This seems to compile fine with clang++ 14.0...

The Dreams Wind
  • 8,416
  • 2
  • 19
  • 49
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    It's interesting, that if you mark the definition with `template<>` it becomes invalid for clang, but valid for gcc - https://godbolt.org/z/GGjjcnPMx – The Dreams Wind Aug 24 '22 at 22:11
  • @TheDreamsWind: That's right... my IDE was complaining about the template<>, but actually it seems like it should be there... or should it? – einpoklum Aug 24 '22 at 22:33
  • [temp.mem.enum](https://eel.is/c++draft/temp.mem.enum) is the closest part of standard i've managed to find so far, but it has nothing about specialisation/instantiation restrictions – The Dreams Wind Aug 24 '22 at 22:38
  • The above code compile with Visual Studio. However the fact that not compiler agree might indicate an area that is not yet well defined... and probably not very used. Do you any reason of mixing template and forward declared enumerations? – Phil1970 Aug 24 '22 at 22:40
  • 2
    See [CWG 1485 Out-of-class definition of member unscoped opaque enumeration](https://cplusplus.github.io/CWG/issues/1485). – cpplearner Aug 25 '22 at 06:50
  • @Phil1970: Yes. I declare the template in a more general header, along with other stuff in struct foo (it's basically a traits class) and define the enum values in separate headers that are related to the specific instantiation. – einpoklum Aug 25 '22 at 07:44
  • Then, why not put the template specialization in the same header where the enum is defined? Alternatively, why not defining top level `enum` and put have something like `enum kind1_named; template <> struct foo { using named = kind1_named; };` – Phil1970 Aug 25 '22 at 21:09
  • @Phil1970: Because the specialization has very few requirements, while all sorts of declarations depend on it. – einpoklum Aug 25 '22 at 22:52

0 Answers0