28

boost :: promptに似ていますが、C++11用のプロモーションテンプレートエイリアスを作成しています。これの目的は、varidic関数から引数を取得するときの警告を回避することです。例えば

template <typename T>
std::vector<T> MakeArgVectorV(int aArgCount, va_list aArgList)
{
    std::vector<T> args;
    while (aArgCount > 0)
    {
        args.push_back(static_cast<T>(va_arg(aArgList, Promote<T>)));
        --aArgCount;
    }
    return args;
}

プロモートテンプレートエイリアスは、可変個引数のデフォルトの引数プロモートに従って型をプロモートします。1)intよりも小さい整数がintにプロモートされます。2)floatがdoubleにプロモートされます。

私の問題は、標準のC ++列挙型はプロモートできますが、C ++ 11列挙型クラスはプロモートされないことです(コンパイラーは警告を生成しません)。Promoteを通常の列挙型で動作させたいのですが、C++11列挙型クラスを無視します。

プロモートテンプレートエイリアスの列挙型クラスと列挙型の違いをどのように見分けることができますか?

4

2 に答える 2

43

考えられる解決策は次のとおりです。

#include <type_traits>

template<typename E>
using is_scoped_enum = std::integral_constant<
    bool,
    std::is_enum<E>::value && !std::is_convertible<E, int>::value>;

このソリューションは、C++11標準のパラグラフ7.2/9で指定されているスコープ付き列挙とスコープなし列挙の動作の違いを利用しています。

列挙型またはスコープ外の列挙型のオブジェクトの値は、汎整数拡張(4.5)によって整数に変換されます。[...]この暗黙の列挙型からint型への変換は、スコープ付き列挙型には提供されないことに注意してください。[...]

これは、それをどのように使用するかのデモンストレーションです。

enum class E1 { };
enum E2 { };
struct X { };

int main()
{
    // Will not fire
    static_assert(is_scoped_enum<E1>::value, "Ouch!");

    // Will fire
    static_assert(is_scoped_enum<E2>::value, "Ouch!");

    // Will fire
    static_assert(is_scoped_enum<X>::value, "Ouch!");
}

そして、これが実際の例です。

謝辞:

以前のアプローチは、ユーザー定義ののオーバーロードがない場合にのみ機能することを指摘してくれたDanielFreyに感謝しoperator +ます。

于 2013-03-23T11:40:37.353 に答える
1

C ++ 23以降、@AndyProwlによって提供されるものと同様のソリューションがtype_traitsから利用できるようになります

#include <type_traits>

enum E { a, b };
enum class Es { x, y, z };

std::is_scoped_enum_v<E>;  // False
std::is_scoped_enum_v<Es>; // True
于 2021-08-09T20:26:31.677 に答える