如何编写C++ Concept确保序列所有索引的类型均已定义
问题描述
现有一套可特化的索引式类型特征(type trait),代码实现如下:
// Traits template <size_t Idx, typename T> struct nth_type; template <size_t Idx, typename T> using nth_type_t = typename nth_type<Idx, T>::type; template <typename T> struct num_types; template <typename T> inline constexpr size_t num_types_v = num_types<T>::value; // Specialization template <typename... Ts> struct type_sequence {}; template <size_t Idx, typename... Ts> struct nth_type<Idx, type_sequence<Ts...>> : std::type_identity<std::tuple_element_t<Idx, std::tuple<Ts...>>> {}; template <typename... Ts> struct num_types<type_sequence<Ts...>> { static constexpr size_t value = sizeof...(Ts); };
需要编写一个C++ Concept has_types,要求对于任意类型T,区间[0, num_types_v<T>)内的每一个索引Idx,typename nth_type<Idx, T>都合法且代表一个类型。无需手动枚举所有索引,达到如下示例的效果:
template<typename T> concept has_types = requires { typename nth_type<0, T>; typename nth_type<1, T>; // ... typename nth_type<num_types<T> - 1, T>; };
解决方案
可以借助std::index_sequence生成目标区间的所有索引,再通过折叠表达式(fold expression)逐个验证每个索引对应的nth_type是否合法,实现如下:
#include <utility> // 用于std::index_sequence和std::make_index_sequence #include <type_traits> // 用于std::type_identity // 辅助模板:验证给定索引序列中的所有索引对应的nth_type是否合法 template <typename T, size_t... Idxs> constexpr bool all_nth_type_valid(std::index_sequence<Idxs...>) { // 折叠表达式:对每个Idx,检查requires { typename nth_type<Idxs, T>; }是否成立 return (requires { typename nth_type<Idxs, T>; } && ...); } // 目标Concept template <typename T> concept has_types = all_nth_type_valid<T>(std::make_index_sequence<num_types_v<T>>{});
原理说明
std::make_index_sequence<N>会生成一个包含0, 1, ..., N-1的索引序列,这里N就是num_types_v<T>,刚好覆盖需求的区间[0, num_types_v<T>)。- 辅助函数
all_nth_type_valid接收这个索引序列,通过折叠表达式(requires { ... } && ...),将每个索引对应的typename nth_type<Idx, T>合法性检查逻辑展开,只有所有检查都通过时,返回值才为true。 has_typesConcept直接依赖这个辅助函数的返回结果,满足需求。
内容的提问来源于stack exchange,提问作者maddisoj
相关产品推荐
相关产品推荐

