C++中的模板元编程

目录

概述

模板元编程可以说是C++中最困难也是最强大的编程范式。模版元编程不同于普通的运行期程序,它执行完全是在编译期,并且它操纵的数据不能是运行时变量,只能是编译期常量(且不可修改)。因此,模版元编程需要很多技巧,在这里你会遇到非常多的枚举常量、继承、模板偏特化、可变模板参数、类型萃取等方法,如果要读懂STL库,那么模板元编程必须要掌握;不仅如此,C++中的许多黑科技都是依赖于模板元编程的,例如我们甚至可以写出编译期排序的算法

模板元编程:template meta programing

前置知识

模板元编程又两个部分组成:元数据和元函数。元数据是指编译期能在编译期处理的数据,即编译期常量;元函数指操纵元数据的函数,在编译期调用,它通常表现为一个模板类或一个模板函数

模板元编程十分特殊,它无法使用if-elseforwhile这些运行期语句,在模板元编程中,我们时常会使用到这些语法:

  • enum,static-constexpr:用来定义编译期的整数常量
  • usingtypedef:定义元数据
  • T,Ts...:用来声明元数据类型
  • template:定义元函数
  • :::用来解析类型作用域获取元数据

constexpr

type_traits

<type_traits>是C++11提供的模板元基础库,它提供了模板元编程中需要的常用的基础元函数

std::integral_constant,定义编译期常量

举个例子,C++11中提供了std::integral_constant来定义编译期常量

template<typename T>
using one_constant = std::integral_constant<T, 1>;

template<typename T>
struct one_struct : std::integral_constant<T, 1> {};

因此我们可以使用one_constant<int>::valueone_struct<int>::value来获取编译期常量int 1

而在C++11之前,我们定义这个常量就需要用到enum或static-const

struct one_struct
{
    enum { value = 1 };
};
struct one_struct
{
    static const int value = 1;  
};

然后通过one_struct::value来访问值,其中enum能隐式转换为int

std::integral_constant的实现也非常的简单

template <class _Ty, _Ty _Val>
struct integral_constant {
    static constexpr _Ty value = _Val;

    using value_type = _Ty;
    using type       = integral_constant;

    constexpr operator value_type() const noexcept {
        return value;
    }

    _NODISCARD constexpr value_type operator()() const noexcept {
        return value;
    }
};

可以看到,通过C++11的<type_traits>提供的一个简单的std::integral_constant就可以很方便的定义编译期常量,而无需再去使用enum和static-const。紧接着,库中又提供了编译期常量的bool类型

using true_type  = bool_constant<true>;
using false_type = bool_constant<false>;

std::integer_sequence,定义编译期整数序列

为什么说是整形呢,请看源码

// 一个类型加上一个非类型模板参数包
template <class _Ty, _Ty... _Vals>
struct integer_sequence { // sequence of integer parameters
    static_assert(is_integral_v<_Ty>, "integer_sequence<T, I...> requires T to be an integral type.");

    using value_type = _Ty;

    _NODISCARD static constexpr size_t size() noexcept {
        return sizeof...(_Vals);
    }
};
上一篇:【】std::integral_constant语法


下一篇:【C#表达式树 五】工厂模式创建表达式树节点