Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward-declare a member enumeration of a class template

With C++11's strongly typed enums, it is possible to declare a member enumeration of a class like so:

class X {
public:
    enum class E;
};

enum class X::E { a, b };

However, when making X a class template:

template <typename T>
class X {
public:
    enum class E;
};

template <typename T>
enum class X<T>::E { a, b };

gcc 4.7.2 and clang 3.0 both complain with "error: ‘enum X::E’ is an enumeration template [-pedantic]" and "error: enumeration cannot be a template", respectively. The section of the standard I think is relevant (and which, in fact, this question originated from) is §14 Templates, the first paragraph of which states:

The declaration in a template-declaration shall

  • declare or define a function or a class, or
  • define a member function, a member class, a member enumeration, or a static data member of a class template or of a class nested within a class template, or
  • define a member template of a class or class template, or
  • be an alias-declaration.

(emphasis mine). So is this a compiler bug, or am I mis-interpreting the statement entirely?

like image 710
Taral Avatar asked Mar 17 '14 11:03

Taral


People also ask

How do I forward declare a class template in Java?

Forward-declaring class templates is as easy as a normal class declaration: template <typename T, typename U> class X; It is also possible to provide forward declarations for specializations of those class templates: template <typename U> class X<int, U>; template <> class X<int, int>;

Is it possible to provide forward declarations for specializations of class templates?

It is also possible to provide forward declarations for specializations of those class templates: When we instantiate a class template that is parametrized with one of our types, the question arises whether it is sufficient to only have a forward declaration of our type.

Why can’t we forward-declare enums?

It needs one if we use one of its members or the base class, or if it has to know how large objects of that class are. One should think that the same applies to enums, but that’s not the case. Forward-declaring plain old enums is not possible. The good news is, that we can provide forward declarations for scoped enums aka. enum classes.

Can I add a forward declaration to a string template?

Do not do this! It’s simply wrong. std::string is not a class, but a typedef to std::basic_string. And no, you can’t simply add a forward declaration to template class basic_string; because that’s not all there is to it, either.


1 Answers

I have been asked for creating this answer. See paragraph [temp.mem.enum] 14.5.1.4/1 of the C++ standard:

An enumeration member of a class template may be defined outside the class template definition. [ Example:

template<class T> struct A {
  enum E : T;
};
A<int> a;
template<class T> enum A<T>::E : T { e1, e2 };
A<int>::E e = A<int>::e1;

—end example ]

Newer version of clang (3.4) compiles your code successfully with flag -pedantic-errors whereas gcc 4.8.1 still considers it is an error. I think it is a gcc bug.

like image 119
Constructor Avatar answered Sep 28 '22 00:09

Constructor