C++模板元编程(二)

C++模板元编程(二)

  模板元编程技术的一个最基本应用:为传统的不进行类型检查的操作添加静态类型检查。

静态类型检查

  以物理计算为例,物理中的数值常常不是独立存在的,它们往往带有量纲。所以不仅有数值的计算,还有量纲的计算。如两个不同量纲的数值的加减往往是没有意义的,而不同量纲数值的乘除计算得到的结果往往是不同的物理量。将量纲看为类型,那么在物理数值计算中进行静态类型检查是很有意义的。举例如下:

/*************************************************************************
    > File Name: physical_quantity.cpp
    > Author: corfox
    > Mail: corfox@163.com 
    > Created Time: 2015/12/31 22:26:22
 ************************************************************************/

#include <iostream>
#include <cassert>
#include <type_traits>
using namespace std;

namespace pq {
    template<int v> 
    struct Int
    {
        static const int value = v;
    };

    // 定义一个量纲模板类
    template<typename T, int v1, int v2, int v3, int v4, int v5, int v6, int v7>
    struct Dimension 
    {
        static const int d1 = v1;
        static const int d2 = v2;
        static const int d3 = v3;
        static const int d4 = v4;
        static const int d5 = v5;
        static const int d6 = v6;
        static const int d7 = v7;
        typedef T value_type;
    };

    // 外包一层(Traits技术),以便物理量乘除计算时,能获得计算结果的新量纲
    template<typename T1, typename T2>
    struct DimensionOperation
    {
        typedef Dimension<typename T1::value_type, T1::d1 + T2::d1, T1::d2 + T2::d2,
                T1::d3 + T2::d3, T1::d4 + T2::d4, T1::d5 + T2::d5, 
                T1::d6 + T2::d6, T1::d7 + T2::d7> plus_type;
        typedef Dimension<typename T1::value_type, T1::d1 - T2::d1, T1::d2 - T2::d2,
                T1::d3 - T2::d3, T1::d4 - T2::d4, T1::d5 - T2::d5,
                T1::d6 - T2::d6, T1::d7 - T2::d7> minus_type;
    };

    // 特化一些常用量纲
    typedef Dimension<int, 1, 0, 0, 0, 0, 0, 0> Mass;
    typedef Dimension<int, 0, 1, 0, 0, 0, 0, 0> Length;
    typedef Dimension<int, 0, 0, 1, 0, 0, 0, 0> Time;
    typedef Dimension<int, 0, 0, 0, 1, 0, 0, 0> Charge;
    typedef Dimension<int, 0, 0, 0, 0, 1, 0, 0> Temperature;
    typedef Dimension<int, 0, 0, 0, 0, 0, 1, 0> Intensity;
    typedef Dimension<int, 0, 0, 0, 0, 0, 0, 1> AmountOfSubstance;
    typedef Dimension<int, 0, 1, -1, 0, 0, 0, 0> Velocity;
    typedef Dimension<int, 0, 1, -2, 0, 0, 0, 0> Acceleration;
    typedef Dimension<int, 1, 1, -1, 0, 0, 0, 0> Momentum;
    typedef Dimension<int, 1, 1, -2, 0, 0, 0, 0> Force;

    template<typename T, typename D>
    class Quantity
    {
        private:
            T value;
        public:
            explicit Quantity(T v) : value(v) {}

            T getValue() const { return value; }

            friend ostream& operator<<(ostream& out, const Quantity& y)
            {
                out << y.getValue();
                return out;
            }

            friend Quantity operator+(const Quantity& x, const Quantity& y)
            {
                return Quantity(x.getValue() + y.getValue());
            }

            friend Quantity operator-(const Quantity& x, const Quantity& y)
            {
                return Quantity(x.getValue() - y.getValue());
            }
    };

    template<typename T, typename D1, typename D2>
    Quantity<T, typename DimensionOperation<D1, D2>::plus_type>
    operator*(const Quantity<T, D1>& x, const Quantity<T, D2>& y)
    {
        return Quantity<T, typename DimensionOperation<D1, D2>::plus_type>(x.getValue() + y.getValue());
    }

    template<typename T1, typename D1, typename D2>
    Quantity<T1, typename DimensionOperation<D1, D2>::minus_type>
    operator/(const Quantity<T1, D1>& x, const Quantity<T1, D2>& y)
    {
        return Quantity<T1, typename DimensionOperation<D1,  D2>::minus_type>(x.getValue() + y.getValue());
    }
}

int main()
{
    pq::Quantity<float, pq::Length> l1(1.0f);
    pq::Quantity<float, pq::Length> l2(2.0f);
    pq::Quantity<float, pq::Mass> m1(3.0f);
    cout << l1 + l2 << endl;
    cout << l1 - l2 << endl;
    cout << l1 * l2 << endl;
    cout << l1 / l2 << endl;
    cout << l1 * m1 << endl;
//  cout << l1 + m1 << endl;
    return 0;
}

参考资料

  1. 《C++模板元编程》(David Abrahams, Aleksey Gurtovoy )
posted @ 2016-01-01 19:54  corfox  阅读(268)  评论(0编辑  收藏  举报