zoukankan      html  css  js  c++  java
  • 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 )
  • 相关阅读:
    转载:人家编写的程序:「雀神 AI」Suphx
    一千六百万单表建联合索引对查询效率的提升
    索引对单列极值查询的显著性影响(百万级别表单列最值查询 Cost由1405变成3)
    经典SQL问题:Top 10%
    区间查询与等效minus查询
    『科学计算』L0、L1与L2范数_理解
    『Python』__getattr__()特殊方法
    『Json』常用方法记录
    『Pickle』数据结构持久化模块_常用方法记录
    『Re』知识工程作业_主体识别
  • 原文地址:https://www.cnblogs.com/corfox/p/5414993.html
Copyright © 2011-2022 走看看