yohhoyの日記

技術的メモをしていきたい日記

列挙型へのスコープ明示指定

プログラミング言語C++の列挙型(enum)と、スコープ解決演算子(scope resolution operator)::に関するメモ。C++11以降では、C++03以前からあるスコープ無し列挙型(unscoped enumeration)に対しても::演算子を適用可能となった。

enum E { A };
E e1 = A;
// C++03/11: OK

E e2 = E::A;
// C++03: NG
// C++11: OK

gcc 4.9.1でのエラー出力例:

$ g++ source.cc -std=c++98 -pedantic
error: 'E' is not a class or namespace

C++03以前

::演算子の左オペランドに記述可能なのは、クラス名または名前空間名のみ。C++03 5.1/p7より一部引用。

7 (snip)
qualified-id:
  ::opt nested-name-specifier templateopt unqualified-id
  (snip)
nested-name-specifier:
  class-or-namespace-name :: nested-name-specifieropt
  class-or-namespace-name :: template nested-name-specifier
class-or-namespace-name:
  class-name
  namespace-name

C++11以降

::演算子の左オペランドとして、クラス名、名前空間名、列挙型名、decltype指定子のいずれかを記述できる。C++11 5.1.1/p8, 10, 7.1.6.2/p1より一部引用。

8 (snip)
qualified-id:
  nested-name-specifier templateopt unqualified-id
  (snip)
nested-name-specifier:
  ::opt type-name ::
  ::opt namespace-name ::
  decltype-specifier ::
  nested-name-specifier identifier ::
  nested-name-specifier templateopt simple-template-id ::

10 A nested-name-specifier that denotes an enumeration (7.2), followed by the name of an enumerator of that enumeration, is a qualified-id that refers to the enumerator. The result is the enumerator. The type of the result is the type of the enumeration. The result is a prvalue.

1 (snip)
type-name:
  class-name
  enum-name
  typedef-name
  simple-template-id
decltype-specifier:
  decltype ( expression )