# 模板元编程——《C++程序设计语言（第四版）》第28章 元编程 笔记

xiaoxiao2021-02-28  3

## 类型函数

### 类型别名

template<typename C, typename T, typename F> using Conditional = typename std::conditioanl<C, T, F>::type;

conditional<is_integral<T>::value, make_unsigned<T>, Error<T>>::type

### 类型谓词

template<typename T> void copy(T* p, const T* q, int n) { if (is_pod<T>()) //... }

### 选择函数

struct X { void operator()(int x) { cout << "X" << x << "!" } //... }; struct Y { void operator()(int y) { cout << "Y" << y << "" } //... }; void f() { Conditional<(sizeof(int) > 4), X, Y> {} (7); using Z = Conditioanl<(Is_polymorphic<X>()), X, Y>; Z zz; zz(7); }

### 萃取

template<typename Iterator> struct iterator_traits { using difference_type = typename Iterator::difference_type; using value_type = typename Iterator::value_type; using pointer = typename Iterator::pointer; using reference = typename Iterator::reference; using iterator_category = typename Iterator::iterator_category; } template<typename Iter> Iter search(Iter p, Iter q, typename iterator_traits<Iter>::value_type val) { typename iterator_traits<Iter>::difference_type m = q - p; }

## 控制结构

### 迭代和递归

template<int N> constexpr int fac() { return N*fac<N - 1>(); } template<> constexpr int fac<1>() { return 1; } constexpr int x5 = fac<5>();

template<int N> struct Fac { static const int value = N * Fac<N - 1>::value; }; tempalte<> struct Fac<1> { static const int value = 1; }; constexpr int x7 = Fac<7>::value;

## 条件定义：Enable_if

### 使用Enable_if

template<typename T> class vector<T> public: vector(size_t n, const T& val); template<typename Iter, typename = Enable_if<Input_iterator<Iter>(),Iter>> vector(Iter b, Iter e); //... }; template<typename T> class vector<T> public: vector(size_t n, const T& val); template<typename Iter> vector(Enable_if<Input_iterator<Iter>(),Iter>> b, Iter e); //... };

### 实现Enable_if

Enable_if的实现相当简单，如下

template<bool B, typename T = void> struct std::enable_if { typedef T type; }; template<typeanme T> struct std::enable_if<false, T> {}; template<bool B, typename T = void> using Enable_if = typename std::enable_if<B, T>::type;

### Enable_if例子

struct substitution_failure {}; template<typename T> struct substitution_succeeded : std::true_type {}; template<> struct substitution_succeeded<substitution_failure> : std::false_type {}; template<typename T> struct has_f : substitution_succeeded<typename get_f_result<T>::type> {}; template<typename T> struct get_f_result { private: template<typename X> static auto check(X const& x) -> decltype(f(x)); static substitution_failure check(...); public: using type = decltype(check(std::decltype<T>())); };

## 国际标准单位例子

### Unit

template<int M, int K, int S> struct Unit { enum { m = M, kg = K, s = S }; }; using M = Unit<1, 0, 0>; using Kg = Unit<0, 1, 0>; using S = Unit<0, 0, 1>; using MpS = Unit<1, 0, -1>; using MpS = Unit<1, 0, -2>; template<typename U1, typename U2> struct Uplus { using type = Unit<U1::m + U2::m, U1::kg + U2::kg, U1::s + U2::s>; }; template<typename U1, U2> using Unit_plus = typename Uplus<U1, U2>::type; template<typename U1, typename U2> struct Uminus { using type = Unit<U1::m - U2::m, U1::kg - U2::kg, U1::s - U2::s>; }; template<typename U1, U2> using Unit_minus = typename Uminus<U1, U2>::type;

### Quantity

template<typename U> struct Quantity { double val; explicit Quantity(double d) : val{d} {} }; Quantity<M> x{10.5}; Quantity<S> y{2}; template<typename U> Quantity<U> operator+(Quantity<U> x, Quantity<U> y) { return Quantity<U> {x.val + y.val}; } template<typename U> Quantity<U> operator-(Quantity<U> x, Quantity<U> y) { return Quantity<U> {x.val - y.val}; } template<typename U1, typename U2> Quantity<Unit_plus<U1, U2>> operator*(Quantity<U1> x, Quantity<U2> y) { return Quantity<Unit_plus<U1, U2>> {x.val * y.val}; } template<typename U1, typename U2> Quantity<Unit_minus<U1, U2>> operator/(Quantity<U1> x, Quantity<U2> y) { return Quantity<Unit_minus<U1, U2>> {x.val / y.val}; }

### Unit字面值常量

constexpr Quantity<M> operator"" _m(double d) { return Quantity<M>{d}; } constexpr Quantity<Kg> operator"" _kg(double d) { return Quantity<Kg>{d}; } constexpr Quantity<S> operator"" _s(double d) { return Quantity<S>{d}; } auto distance = 10_m; auto time = 20_s; auto speed = distance / time;