name types_link
::type; };
每次取出第一个元素,然后把它放到最后面即可。
六、types的排序
在编译期排序和运行期其实并没什么不同,只是算法的选择上需要考虑一下。假设是从大到小排列,那么最直观的想法是每次递归都从types中找到最大的元素,然后把它放到头上去。这样递归完毕后整个types就是有序的了。
这种想法其实就是选择排序(Selection sort)。
当然,我们也可以实现插入,或者快排。如果读者感兴趣的话,可以自己实现一下。
使用选择排序,首先需要能从types中找到放在最前面的那个元素。在这里我们不使用现成的比较算法,而写成可以让外部指定比较算法。那么select的算法定义如下:
template
class If_>
struct types_select_if : check_is_types
{ using type = TypesT; };
我们先用数学归纳法思考下算法:
当types中只有1个元素T1时,直接返回T1;(终结条件)
当types中有1个元素以上时,先得到T1以外的其它元素的select结果(S),然后将T1和S一起放入If_中。若If_为true,那么选择T1,否则选择S。
同样,先列出特化条件:
, If_>
, If_>
然后是它们的实现:
template
class If_>
struct types_select_if
, If_> { using type = T1; }; template
class If_> struct types_select_if
, If_> { private: using select_t = typename types_select_if
, If_>::type; public: using type = typename std::conditional
::value, T1, select_t>::type; };
可以看到,代码和前面归纳法的描述是一致的。
接下来,是排序的实现。首先是定义:
template
class If_>
struct types_sort_if : check_is_types
{ using type = TypesT; };
和上面一样,先用数学归纳法思考下:
当types中只有1个元素T1时,直接返回types
;(终结条件)
当types中有1个元素以上时,先得到types的select结果(S),之后从types中删除S,然后对结果递归运算,最后把S连接到头部。
列出特化条件:
, If_>
, If_>
最后是实现:
template
class If_>
struct types_sort_if
, If_> { using type = types
; }; template
class If_> struct types_sort_if
, If_> { private: using types_t = types
; using sl_t = typename types_select_if
::type; using er_t = typename types_erase
::value>::type; using tail = typename types_sort_if
::type; public: using type = typename types_link
::type; };
我们来看看排序的效果:
using types_t = types
;
template
struct is_large : std::integral_constant
sizeof(U))> {}; using sort_t = types_sort_if
::type; // sort_t = types
尾声
实际项目中,我们往往不会像这样写这么多模板元的代码。如果有类似需求,可能会考虑直接使用Boost.MPL,或者在Loki.TypeList的基础上加一层变参模板的外敷。
自己完整的实现一次模板元的容器操作算法的意义,在于可以大大加深对模板元编程,以及对变参模板的理解。
有了这些经验之后,在不方便使用第三方库时,能够快速自撸一些简单且可靠的模板元算法,来完成一些编译期计算的需求;同时也可以帮助我们更清晰的理解和分析一些C++模板库(STL、Boost之类)里的泛型算法。
另外,目前的std::tuple的实现方式其实是类似上面的types的。比如gnuc的libstdc++里的定义:
// Forward declarations.
template
class tuple;
而目前stl里对std::tuple的编译期操作很简单,只有std::tuple_size和std::tuple_element两种。如果想增加std::tuple的编译期运算功能,也可以自行采用上面类似的算法做拓展。
完整代码及测试下载请点击:types
Wrote by mutouyun. (http://darkc.at/cxx-type-list/)