如果您想避免手动类型递归,
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 > {};
template<typename What, typename... Args> constexpr inline bool is_present_v = (std::is_same_v<What, Args> || ...);
- Vladislav