12

C ++ 11では、構文が。の強い型付き列挙型が導入されましたenum class。これらは整数型と互換性がなく、数値を取得するには明示的なキャストが必要です。C ++ 11には、弱い型の列挙型のストレージクラスを形式で指定する機能も導入されていますenum name : type {}。これはここまでは問題ありません。

しかし、弱い型の列挙型に特定のストレージクラスがある場合でも、そのアイテムの型はまだintです。Visual Studio 2012、11月のCTPリリースで試してみました。次のコードを検討してください。

enum charEnum : char { A = 'A' };
enum longEnum : long long { Tera = 1000000000000 };

void fct(char val) {}
void fct(int val) {}
void fct(long long val) {}

int main() 
{
    static_assert(sizeof(A) == sizeof(char), "check charEnum size");
    static_assert(sizeof(Tera) == sizeof(long long), "check longEnum size");
    fct('A');  // calls fct(char)
    fct(1);    // calls fct(int)
    fct(2ll);  // calls fct(long long)
    fct(A);    // calls fct(int) !
    fct(Tera); // calls fct(int), with truncation !
    fct((long long)Tera);  // calls fct(long long)
    return 0;
}

列挙値を要求するオーバーロードされた関数は、値がfct(int)切り捨てられた場合でも、常にです。もちろん、明示的なキャストを使用すると、オーバーロードされた関数を呼び出すことができますが、これは従来のC++03構文でも可能でした。

明らかな何かが欠けていますか?何故ですか?明示的なキャストよりも優れた回避策はありますか?

4

1 に答える 1

9

これはコンパイラのバグです。§7.2/9および§4.5/4によると:

§7.2/9:
列挙型またはスコープ外の列挙型のオブジェクトの値は、汎整数拡張によって整数に変換されます(4.5)

§4.5/4:
基になる型が固定されているスコープなし列挙型のprvalue(7.2)は、基になる型のprvalueに変換できます。さらに、汎整数拡張をその基礎となる型に適用できる場合、基礎となる型が固定されているスコープなし列挙型のprvalueも、プロモートされた基礎となる型のprvalueに変換できます。

最後のものはlong long、ではなく、に変換する必要がありintます。事件はchar論点です。(!)


テストプログラム:

#include <iostream>

enum charEnum : char      { A = 'A' };
enum longEnum : long long { Tera = 1000000000000 };

void fct(char val)      { std::cout << "fct(char)"      << std::endl; }
void fct(int val)       { std::cout << "fct(int)"       << std::endl; }
void fct(long long val) { std::cout << "fct(long long)" << std::endl; }

int main() 
{
    static_assert(sizeof(A)    == sizeof(char),      "check charEnum size");
    static_assert(sizeof(Tera) == sizeof(long long), "check longEnum size");

    fct('A');
    fct(1);
    fct(2ll);
    fct(A);
    fct(Tera);
    fct((long long)Tera);
}

MSVC2012NovCTP出力:

fct(char)
fct(int)
fct(long long)
fct(int)
fct(int)
fct(long long)

g ++ 4.7.1:

fct(char)
fct(int)
fct(long long)
fct(int)
fct(long long)
fct(long long)

于 2013-01-06T18:47:14.507 に答える