C++11中type_traits中的基石 - integral_constant

C++标准库的的编写方法是基于模板元来编程的,既然是用模板,那么就少不了与类型打交道,而C++11标准库中新加入了头文件,这个里面新加入了很多与类型特性有关的模板元,在编译期间这些东西就是利器,非常好用。

而打开头文件,看到的第一个模板类就是integral_constant,这个类是type_traits的基石,基本上type_traits都直接或间接继承自integral_constant,而且,C++标准库中还有很多模板类也是继承了integral_constant,例如std::ratio

integral_constant的意思是积分常量,这是我Google 回来的意思,其实,这个类就是提供了一个编译期常量。

先来看看源码:

/// integral_constant
template<typename _Tp, _Tp __v>
struct integral_constant
{
    static constexpr _Tp                  value = __v;
    typedef _Tp                           value_type;
    typedef integral_constant<_Tp, __v>   type;
    constexpr operator value_type() const
    {
        return value;
    }
#if __cplusplus > 201103L

#define __cpp_lib_integral_constant_callable 201304

    constexpr value_type operator()() const
    {
        return value;
    }
#endif
};

template<typename _Tp, _Tp __v>
constexpr _Tp integral_constant<_Tp, __v>::value;

可以看到,integral_constant只有一个静态常量表达式变量value,由于是静态变量,因此要在类外声明;

然后就是两个typedef,这是traits的老套路了,喜欢在类中重定义一些类型,说白了就是把别人东西的包一层,然后作为一个中间层告诉用户需要的东西;

接着就是两个操作符重载了。

在C++14中重载了函数运算符,这非常有用,假设现在你需要写一个函数,这个函数返回App的版本号,这个版本号是个常量,不会变(假设啊),你肯定会这么写:

#define APP_VERSION 20181010L
const char * GetAppVersion() { return APP_VERSION; }

那么在C++14中,你可以这么写:

struct GetAppVersion : public std::integral_constant<unsigned int, APP_VERSION> {};

然后像函数一样调用就行了,auto appVersionString = GetAppVersion(),非常好用。因此,凡是需要返回一些常量的函数都可以这么写。

到这里,源码就分析完了,是不是特别简单,但是,这东西有什么用呢?貌似还没有说清楚。

先来看看三个特别重要的东西:

/// The type used as a compile-time boolean with true value.
typedef integral_constant<bool, true>     true_type;

/// The type used as a compile-time boolean with false value.
typedef integral_constant<bool, false>    false_type;

template<bool __v>
using __bool_constant = integral_constant<bool, __v>;

前两个是不是好熟悉啊,看《STL源码剖析》,SGI有一个__type_traits也有__true_type__false_type,从前面的两条下划线可以知道,当时的__type_traits只能供内部使用,并不是C++标准规范之中的内容,然后再来看看当时的这两个类型是如何定义的:

struct __true_type {};
struct __false_type {};

把这两个定义和C++11中的两个定义比较一下,你就会发现,C++11的true_type / false_type是多么有血有肉,调用std::true_type::value还可以得到true

这也是为什么我之前说type_traits中的大部分类都直接或间接继承自integral_constant,你可以继续看看type_traits中其他类,凡是带前缀is_*的类的偏特化特化都是继承自true_type。例如下面的__is_pointer_helper

template<typename>
struct __is_pointer_helper : public false_type { };

template<typename _Tp>
struct __is_pointer_helper<_Tp*> : public true_type { };

这种例子在type_traits中比比皆是。

__bool_constant这是一个辅助类型重定义,可以用在模板函数重载中。

integral_constant的另一作用就是用在std::ratio编译器分数类中,这个在另一篇博客会有介绍。

目前解除到的关于integral_constant就这么多,以后有机会再完善。

你可能感兴趣的:(C/C++技巧)