私は現在、名前空間付きの列挙型または静的定数の名前空間付きのグループが望ましいかどうかという問題について考えています。デフォルトの選択は何ですか?またその理由は何ですか?
オプション1:
namespace Direction
{
enum Direction
{
north,
east,
south,
west,
};
}
オプション 2:
namespace Direction
{
static const unsigned char north = 0;
static const unsigned char east = 1;
static const unsigned char south = 2;
static const unsigned char west = 3;
}
どちらにも長所と短所があります。
プロ列挙:
いくつかのタイプセーフ:
void foo(Direction dir); // the compiler won't allow you to just pass an int or a value of an unrelated enum without explicitly casting it
対照列挙:
型の安全性はかなり制限されています:
enum A { Entry1 = 1 }; enum B { Entry2 = 10 }; A a; if(a == Entry2) ; // ouch!
int 以外の型はサポートされていません - C++ 11 より前では、long long、short、または char などの列挙型を持つことはできません。
列挙型の名前空間は最適ではありません
列挙型を別の名前空間にラップしないと、そのすべてのメンバーが周囲の名前空間を汚染します。
列挙型を別の名前空間にラップする場合、列挙型自体を型として使用すると冗長性が得られます。次に、Direction::Direction の方法で方向変数を宣言する必要があります (「Direction:: を使用しない場合」方向"、これにより、外側の名前空間が再び汚染され(最後に、 using ディレクティブが有効になるコードのその部分で)、北だけでなく方向::北の方法でそのメンバーの名前を付けることができます
プロ静的定数:
- C++ 11 より前の C++ での型サポートの向上 - たとえば、定数に unsigned char などの型を使用できます
- 適切なスコープ - using ディレクティブを介して明示的に要求することなく、外側の名前空間を汚染しません (その場合でも限られたスコープでのみ)
対照的な静的定数:
列挙型よりも型安全性がさらに低くなります。次のような関数プロトタイプを宣言することはできなくなりました。
void foo(Direction dir);
ただし、次の方法で行う必要があります。
void foo(unsigned char dir); // now each variable of type unsigned char or of a type that can implicitly be casted into unsigned char can be passed, even if its totally unrelated to the expected "enumeration" or if the value does not match the value of any of the expected consts
編集: ここで、列挙型の型安全性の制限に関する興味深い記事を見つけました: http://www.drdobbs.com/enumerations/184401797