16

C ++で列挙型をテンプレート(タイプ)引数として使用する際の制限/問題はありますか?

例:

enum MyEnum
{
    A, B, C, D, E
};

template <typename _t>
class MyTemplate
{
public:
   _t value;

   void func(const _t& param) { /* .... */ }
};

// ....

MyTemplate<MyEnum> MyInstance;

Win32 /x86でVS2008(SP1)を介してMSVC ++を使用する実際の問題は、テンプレート引数として列挙型を使用するクラスに関連するいくつかのコンパイルエラー(=コンパイラによって報告されるエラー)です。残念ながら、私のプロジェクトは少し複雑になっているため(設計エラー:Pと見なすことができます)、これらのエラーを発生させるテンプレートクラスは派生し、ネストされ、enumテンプレートパラメーターを持つクラスに特化されています。

ビルドしようとすると、コンパイラはコメントしかない行に「C2059:構文エラー:'public'」などの多くの間違った/役に立たないエラーを報告します。それらの多くは、例のconst _t&paramを_tに置き換える(つまり、パラメーターをコピーする)ことで修正できますが、これらのエラーをすべて修正することも、これが「役立つ」理由の手がかりもありません。 。**私は知っています、上記の簡単な例はエラーなしでコンパイルします。

enumの代わりにintを使用して、私のプロジェクトはエラーなしでコンパイルします。

ヒントやヒントを事前に感謝します!


編集

結局のところ、私はこれをコンパイラのバグと真剣に考えています。簡略化されたコードでエラーを再現しようとすると、すべての「ビルド」の50%でしかエラーが発生せず、決定論的ではありませんでした。
たとえば、コンパイルしようとすると、これらのエラーが報告されました。再構築-変更なし。コメントを削除し、ビルドします-変更はありません。再構築-そして:エラーなし、正常にコンパイルされます。

私はすでにいくつかのコンパイラのバグに遭遇しました(2または3は2万行のコード内だと思います)が、これは私には非常に奇妙に思えます。それがコンパイラ であるか
どうかを判断する方法について何か提案はありますか?

4

3 に答える 3

7

はい、制限があります。たとえば、C ++ 03に従って、テンプレート引数として匿名列挙型を使用することはできません。14.3.1[temp.arg.type]/2

ローカル型、リンケージのない型、名前のない型、またはこれらの型のいずれかから複合された型は、テンプレート型パラメータのテンプレート引数として使用してはなりません。

したがって、次のコードはC++03では無効です。

template <typename T>
void f(T) {}

enum {A};

int main() {
  f(A);
}

ただし、C++11では有効です。

于 2014-07-03T17:49:10.213 に答える
5

元の質問を参照してください:

C ++で列挙型をテンプレート(タイプ)引数として使用する際の制限/問題はありますか?

何も見つかりませんでした-そして、何もないと思います。この手法はあまり使用されないため、悪い考えになる可能性があります。そのため、Potatoswatterが言ったように、これに関連するコンパイラのバグがいくつか(さらに)ある可能性があります。
次の例を考えてみましょう。

enum MyEnum : int
{
    A, B, C, D
};

template <typename _t> class MyTemplate
{
public:
    void print()
    {
        cout << "not using any specialisation" << endl;
    }
};
    template <> class MyTemplate <MyEnum>
    {
    public:
        void print()
        {
            cout << "MyEnum specialisation" << endl;
        }
    };
    template<> class MyTemplate <int>
    {
    public:
        void print()
        {
            cout << "int specialisation" << endl;
        }
    };

template <typename _t> void print(_t param)
{
    MyTemplate<_t> m;
    m.print();
}


int main()
{
    print(A);
    print(5);

    return 0;
}

出力は次のとおりです。

MyEnumスペシャライゼーション
intスペシャライゼーション

これらの簡単な例では、すべてが正常に期待どおりに機能し、列挙型はテンプレート型引数として他の型と完全に機能します(=問題の理由はわかりません)。

もともと、私はその質問で私が何を意味するかを示すために質問の例を紹介しました(テンプレート型引数として列挙型、メンバーまたはメソッド引数型として可能な使用法を示すなど)。少し背景を説明するために、つまり、なぜ私がその質問をしたのか(「intに問題はありますか」と尋ねたと想像してください)、実際のプロジェクトをコンパイルするこれらの奇妙な問題について言及しました。
申し訳ありませんが、それ自体が完全でエラーを再現しているスニペットを抽出できませんでした。少なくとも、2k行のコードが4つのファイルに分割され、「構文エラー:'public'」などがありました。プロジェクトをコンパイルしたときに構文エラーが発生し、コメントの削除または再構築(=中間ファイルの削除)時に特定の状況で表示/非表示になりました。残念ながら、再構築は元のプロジェクトでは役に立ちません。元のプロジェクトでは、特殊化を列挙型から整数型に置き換える必要がありました。

だから、あなたのヒントとヒントをみんなに感謝します。根本的な問題はコンパイラのバグであるように思われます。答えは「いいえ、テンプレート型の引数として列挙型を使用する制限はありません」であるため、質問は少し無意味になります。ご不便おかけしてすみません。

于 2010-08-15T14:47:33.170 に答える
0

MSVCは、列挙型(値)テンプレートパラメーターを奇妙に処理します。列挙型が不適切にプロモートさintれることがあり、演算子が適切に定義されていません。テンプレートエンジンを型で実際にテストしていないようですenum

コンパイラのバグであることを証明するのは簡単です。有効なコードを挿入して、正常にコンパイルされるかどうかを観察します。あなたの例は明らかに準拠しているので、問題(またはとにかく間違い)は彼らのものです。

編集:詳しく調べてみると、この例ではバグが再現されていないとのことです。あなたがそうする例を生み出すまで、私たちも他の誰もあなたを助けることはできません。

于 2010-08-15T00:46:48.853 に答える