web-dev-qa-db-ja.com

型内で列挙型を使用する-コンパイラの警告C4482 C ++

クラスの1つのメソッド内で列挙型の完全修飾名を使用しています。しかし、私は"警告C4482:非標準の拡張機能が使用されました:修飾名で列挙型 'Foo'が使用されました"というコンパイラ警告を受け取っています。 C++では、修飾名なしで列挙型を使用する必要がありますか?しかし、IMO、それはいようです。

何かご意見は?

65
Navaneeth K N

はい、列挙型は新しい「名前空間」を作成しません。列挙型の値は周囲のスコープで直接利用できます。だからあなたは得る:

enum sample {
  SAMPLE_ONE = 1,
  SAMPLE_TWO = 2
};

int main() {
  std::cout << "one = " << SAMPLE_ONE << std::endl;
  return 0;
}
59
sth

きれいにするには、以下を交換します。

enum Fruit {

    ORANGE = 0,
    BANANA = 1

};

namespace Fruit {

    enum { //no enum name needed

        ORANGE = 0,
        BANANA = 1

    };

};

...

int f = Fruit::BANANA; //No warning
39
Poy

Sthは質問に答えますが、私が常に列挙型をどのように使用しているかについては言及していません。数字の多かれ少なかれ名前ですが、特定の値のみを持つことができる型を定義するために常に使用していました。

列挙型がクラスの一部である場合、消費者は列挙型参照を明確に識別するのに役立ちます。

class Apple {
  enum Variety {
    Gala,
    GoldenDelicious,
    GrannySmith,
    Fuji
  }
  ...
};

次に、コンシューマは列挙型のインスタンスを宣言し、パラメータとして渡し、いずれかの型を参照するときにそれらを修飾できます。

unsigned int GetCountOfApples( Apple::Variety appleVariety );
...
fujiCnt = GetCountOfApples( Apple::Fuji );

クラスの外に列挙型が必要な場合や、同じクラスに2つの列挙型が必要な場合は、Poyのようなものを実行できます。ただし、列挙型を参照することはできないため、名前を付けてください。

namespace Color {
  enum ColorEnum {
    Blue,
    Red,
    Black
  };

列挙型と値を使用すると、次のようになります。

Color::ColorEnum firstColor = Color::Blue;
Color::ColorEnum secondColor = Color::Red;

if( firstColor == secondColor )
....

現在、同じ名前の異なる列挙型が存在する場合、それらは常にそれらのタイプで修飾されます。その後、ギャンブラーが求めていることを処理できます。

BananaColorEnum banCol = BananaColor::Yellow;
TomatoColorEnum tomCol = TomatoColor::Yellow;
15
jmc

はい。概念的に列挙型は、型、およびその型の可能な値を定義します。当然のことですが、enum foo { bar, baz };を定義してからfoo::bazを参照することは、int::1を参照することと同じです。

12
Rob K

namespace Company
{
    typedef int Value;
    enum
    {
        Microsoft= 0,
        Apple = 1, 
    };
};

namespace Fruit
{
    typedef int Value;
    enum
    {
        ORANGE = 0,
        BANANA = 1,
        Apple = 2, 
    };
};

...

Fruit::Value f = Fruit::BANANA; //No warning
Company::Value f = Company::Apple; //is different value then Fruit::Apple

これはGCCおよびMSコンパイラとMacで動作します。そして利点は、名前空間演算子を使用して競合を渡すことができることです。小さな欠点は、Fruitの代わりにFruit :: Valueを書かなければならないことです。他のクラスにある列挙型がわからない場合は、大規模プロジェクトでより便利です。

代わりにC++ 11を使用できる場合、enum :: namespace構文が可能になるため、はるかに簡単です。

9
Tomas Kubes

私がこれを行うことがわかった最もクリーンな方法は、列挙型をそのように定義することです

namespace Samples
{
    enum Value
    {
        Sample1,
        Sample2,
        Sample3
    };
}
typedef Samples::Value Sample;

次に、関数と変数の定義でtypedefを使用できます。

void Function(Sample eSample);
Sample m_eSample;

.cppファイルでは、名前空間を使用して変数を割り当てることができます。

void Function(Sample eSample)
{
    m_eSample = Samples::Sample1;
    eSample = Samples::Sample2;
}
7
petejamd

個人的には、これはコンパイラのバグだと思います。私は長い間C++を使用しています。悲しいことに、OPにはサンプルコードはありません。 Java人々による列挙の解釈は、実際には正しいiMOです。私のものは、このようでした...

class Foo {
    enum tMyEnum { eFirstVal = 0, eSecondVal = 1};
    // ...
    tMyEnum m_myVal;
};
void Foo::MyMethod() {
    if(m_myVal == tMyEnum::eFirstVal) {
//  ...
    }
}

Foo :: tMyEnum :: eFirstValも試しました。修飾子なしで、すべてがコンパイルされました。

1
georgejo

同じ問題があり、C++ 11をまだ使用していません。私も完全に修飾された名前空間を好みます。

この特定の警告を無効にしました。人々はこの考えを嫌うと確信していますが、感謝する人もいるかもしれません。

#pragma warning( disable : 4482 )
0
SparkyNZ