如果您想避免手动类型递归,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
一点。标准说
如果专门化中的至少一个模板参数是用户定义的类型,则程序可以专门化此特征。
并准确描述其中的内容:递归部分特化案例、应用二元运算符的案例和终端案例。本质上,它是一个通用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 > {};