手動の型再帰を回避したい場合std::common_type
は、可変引数テンプレートである STL で唯一のユーティリティであるように思われます。したがって、再帰を潜在的にカプセル化できる唯一のユーティリティです。
解決策 1
std::common_type
型のセットから最小派生型を見つけます。数値を型で識別した場合、特に派生型の少ない数値を識別した場合、集合内で最大の数値が検出されます。次に、キー タイプと同等性を派生レベルにマッピングする必要があります。
using namespace std;
struct base_one { enum { value = 1 }; };
struct derived_zero : base_one { enum { value = 0 }; };
template< typename A, typename B >
struct type_equal {
typedef derived_zero type;
};
template< typename A >
struct type_equal< A, A > {
typedef base_one type;
};
template< typename Key, typename ... Types >
struct pack_any {
enum { value =
common_type< typename type_equal< Key, Types >::type ... >::type::value };
};
解決策 2
common_type
もう少しハッキングできます。基準は言う
特殊化の少なくとも 1 つのテンプレート パラメーターがユーザー定義型である場合、プログラムはこの特性を特殊化できます。
再帰的な部分特殊化のケース、二項演算子を適用するケース、および終端のケースです。基本的に、これは汎用fold
関数であり、任意のバイナリ操作を追加できます。ここでは、OR よりも有益であるため、加算を使用しました。is_same
を返すことに注意してくださいintegral_constant
。
template< typename Addend >
struct type_sum { // need to define a dummy type to turn common_type into a sum
typedef Addend type;
};
namespace std { // allowed to specialize this particular template
template< typename LHS, typename RHS >
struct common_type< type_sum< LHS >, type_sum< RHS > > {
typedef type_sum< integral_constant< int,
LHS::type::value + RHS::type::value > > type; // <= addition here
};
}
template< typename Key, typename ... Types >
struct pack_count : integral_constant< int,
common_type< type_sum< is_same< Key, Types > > ... >::type::type::value > {};