13

動作するように見えるコードを次に示します。

#include <cassert>
#include <limits>

enum test { A = 1 };

int main()
{
    int max = std::numeric_limits<test>::max();
    assert(max > 0);
}

しかし、Linux では GCC (4.6.2) と clang (2.9) の両方で失敗します: 列挙型の max() は実際にはゼロです! これは、C++11 列挙型指定子を使用して、列挙型に必要な型を明示的に指定した場合でも当てはまります。

どうしてこれなの?また、C++11 の動作に関しては、明示的に要求されているものですか? 厳密に型指定された列挙型に関する論文である N2347 では、それについての言及は見つかりませんでした。

4

4 に答える 4

29

std::numeric_limitsboolは、 「(§18.3.2.1/ 2)を含む、浮動小数点と整数の両方の算術型ごとの標準ライブラリに特化しています。

列挙testはこれらのタイプの1つではないため、プライマリテンプレートが使用されます。その動作は§18.3.2.3/1で指定されています:「デフォルトのnumeric_limits<T>テンプレートにはすべてのメンバーが含まれますが、0またはfalse値が含まれます。」

の基になるタイプの特性を知りたい場合はtest、次を使用できますunderlying_type

std::numeric_limits<std::underlying_type<test>::type>::max()

または、特殊化して、必要な値を返すようにすることもできnumeric_limitsますtest。ただし、これは特に良い考えではありません。

于 2012-02-08T21:43:42.560 に答える
3

テンプレートの特殊化されていないバージョンの場合、をmax返しますT()numeric_limitsタイプの特殊化を記述していないtestため、デフォルトの実装を取得します。

于 2012-02-08T21:43:55.403 に答える
1

C++11 ドラフトから:

18.3.2.1では、約numeric_limits:

複合体 (26.4.2) などの非算術標準型には、特殊化があってはなりません。

また、列挙型は算術標準型ではありません。

次に、特殊化されていないテンプレートで:

template<class T> class numeric_limits {
    public:
    [...]
    static constexpr bool is_specialized = false;
    static constexpr T max() noexcept { return T(); }
};

つまり、特殊化されていないmax()関数は、その型のデフォルトの初期化値、つまり 0 を返します。

于 2012-02-08T21:49:03.317 に答える
1

これnumeric_limits<T>は通常のクラス テンプレートであり、ユーザー定義enum型を検出するための特別な方法でコンパイラに接続されることはありません。ファイルを見ると、<limits>すべてに対してゼロを返すデフォルトのテンプレート定義と、個々の型の型固有の仕様が多数含まれており、正しい定数が返されています。

enum自分で の仕様をnumeric_limits提供することで、に「プラグイン」できnumeric_limits<test>ます。intから用のものをコピーし<limits>、必要に応じて変更できます。

于 2012-02-08T21:45:10.607 に答える