web-dev-qa-db-ja.com

列挙型クラスの列挙子にエイリアスを付けることは可能ですか?

C++ 11列挙型クラスが与えられ、いくつかの長くて醜い名前空間内にネストされています。

namespace
    long_and_ugly
{
    enum class
        colour
    {
        red,
        green,
        blue
    };
}

列挙値でエイリアスを作成できますか? clang ++ 3.5では、次のことを実行できます。

using long_and_ugly::colour; // take all the values into the current namespace
using long_and_ugly::colour::red; // take only 'red' into the current namespace

function_taking_colour_argument( red ); // instead of fully referring to the value

ただし、g ++ 4.9は文句を言います。コードにアクセスできないため、エラーメッセージをコピーできませんが、usingディレクティブまたは宣言の使用法について明示的に文句を言いました。私もこれを試しました:

using red = long_and_ugly::colour::red;

しかし、それも失敗しました。エラーを貼り付けずにごめんなさい。それでも、再現できるはずだと思います。


質問

  • 標準のC++ 11で列挙値のエイリアスを宣言することは可能ですか、それともclang拡張機能を使用していましたか?

  • もしそうなら、正しい構文は何ですか?

23
Kalrish

sing-declarationsの列挙子

問題は、sing-declarationを指定して使用する場合、enum class内の列挙子を参照しないように標準で規定されていることです。

7.3.3p7using宣言[namespace.udecl]n3337

sing-declarationは、スコープ付き列挙子を指定してはなりません。

namespace N {
  enum class E { A };
}

using N::E;    // legal
using N::E::A; // ill-formed, violation of [namespace.udecl]p7

clangは上記の両方の行を受け入れます。 関連するバグレポートはこちら

enum class自体の実際の名前を参照することはまったく問題ありませんが、その列挙型の1つを参照しようとすると形式が正しくありません。


alias-declarationsの列挙子

alias-declarationは、type-nameを参照するためにのみ使用できると標準で規定されています。これは、enumeratorが型ではないため、そのような状況で1つを使用することは、形式が正しくありません。

namespace N {
  enum class E { A };
}

using x = N::E;     // legal, `N::E` is a type
using y = N::E::A;  // ill-formed, `N::E::A` isn't a type

sing-およびalias-declarationsの代替

「エイリアス」にしたい値で初期化された、選択した名前の定数を持つ定数を宣言できます。

namespace N {
  enum class E { A };
}

constexpr N::E x = N::E::A;
int main () {
  N::E value = x; // semantically equivalent of `value = N::E::A`
}
26

種類:

namespace long_and_ugly {
    enum class colour
    {
        red,
        green,
        blue
    };
}
const colour red = long_and_ugly::colour::red;
3
MSalters