美文网首页
Boolan STL与泛型编程 第五周作业

Boolan STL与泛型编程 第五周作业

作者: lxidea | 来源:发表于2018-05-28 09:36 被阅读0次

    设计一个Measurement计量单位类型,满足如下要求,

    1. 当为距离单位,当构造米或者千米等不同距离单位的实例时,统一以米为基本单位,实例调用description函数返回单位对应的meter类型(米类型)
    2. 当为时间单位,当构造分钟或者秒为单位的实例时,统一以秒为基本单位,实例调用description函数返回单位对应的second类型(秒类型)
    3. 如果为除距离和时间的其他单位,都打印值即可。

    提示

    请使用Traits来完成该题,通过Traits获取不同计量单位的转换系数和基本单位。
    测试代码

       measurement<meter> m1 = 20;
       measurement<kilometer> m2 = 11.2;
       meter me = m1.description();
    
       measurement<second> m3 = 20;
       measurement<minute> m4 = 10;
    
       measurement<double> m5 = 10;
    
       std::cout << me << std::endl;
       std::cout << m2.description() << std::endl;
       std::cout << m3.description() << std::endl;
       std::cout << m4.description() << std::endl;
       std::cout << m5.description() << std::endl;
    

    为了让Measurement返回的descriptioni函数知道它对应的单位究竟是meter还是second,我们需要将泛化的类传给Traits去获得它所对应的基本单位。
    因此,在type_traits.h中,这样写

    //
    // Created by laixi on 2018/5/28.
    //
    
    #ifndef WEEK10HM_TYPE_TRAITS_H
    #define WEEK10HM_TYPE_TRAITS_H
    
    class meter;
    class kilometer;
    class second;
    class minute;
    class unit;
    
    #include <type_traits>
    #define const_value(x) std::integral_constant<int,x>
    
    typedef std::integral_constant<bool, true> true_type;
    typedef std::integral_constant<bool, false> false_type;
    typedef const_value(1) one;
    
    template <class type>
    class type_traits {
    public:
        typedef false_type __is_time;
        typedef false_type __is_length;
        typedef one coefficient;
        typedef type baseType;
    };
    
    
    template <>
    class type_traits<meter> {
    public:
        typedef false_type __is_time;
        typedef true_type __is_length;
        typedef one coefficient;
        typedef meter baseType;
    };
    
    template <>
    class type_traits<kilometer> {
    public:
        typedef false_type __is_time;
        typedef true_type __is_length;
        typedef const_value(1000) coefficient;
        typedef meter baseType;
    };
    
    template <>
    class type_traits<second> {
    public:
        typedef true_type __is_time;
        typedef false_type __is_length;
        typedef one coefficient;
        typedef second baseType;
    };
    
    template <>
    class type_traits<minute> {
    public:
        typedef true_type __is_time;
        typedef false_type __is_length;
        typedef const_value(60) coefficient;
        typedef second baseType;
    };
    
    #endif //WEEK10HM_TYPE_TRAITS_H
    

    然后,定义我的模板类measurement

    //
    // Created by laixi on 2018/5/28.
    //
    
    #ifndef WEEK10HM_MEASUREMENT_H
    #define WEEK10HM_MEASUREMENT_H
    
    #include "type_traits.h"
    
    template <class U>
    class measurement {
    protected:
        typename type_traits<U>::coefficient coeff;
        U* _unit;
    
    public:
        explicit measurement();
        explicit measurement(const measurement<U>& m);
        measurement operator =(U u);
        measurement operator =(measurement<U> m);
        measurement operator =(float val){
            _unit = new U(val);
        }
        U getUnit() const {return *this->_unit;};
        float value() const {
            return _unit->value;
        };
        typename type_traits<U>::baseType description();
        operator double(){return coeff;};
        measurement(float val){
            _unit = new U(val);
        };
        template <typename T>
                measurement operator= (T val){
            if (!_unit) {
                _unit = new U(val);
            } else
                *_unit = val;
        }
    };
    
    template<class U>
    measurement<U>::measurement(const measurement<U> &m) {
        _unit = new U(*m._unit);
    }
    
    
    template<class U>
    measurement<U> measurement<U>::operator=(U u) {
        if (!_unit) {
            _unit = new U(u);
            return *this;
        }
        if (*_unit != u)
            *_unit = u;
        return *this;
    }
    
    template<class U>
    measurement<U> measurement<U>::operator=(measurement<U> m) {
        if (!_unit) {
            _unit = new U(m.description());
            return *this;
        }
        if (*_unit != m.description())
            *_unit = m.description();
        return *this;
    }
    
    
    template<class U>
    measurement<U>::measurement() {
        _unit = new U();
    }
    
    
    #endif //WEEK10HM_MEASUREMENT_H
    

    为了让measurement有具体的unit的概念,我定义了一个基类unit

    //
    // Created by laixi on 2018/5/28.
    //
    
    #ifndef WEEK10HM_UNIT_H
    #define WEEK10HM_UNIT_H
    
    #include "type_traits.h"
    
    #include <string>
    #include "measurement.h"
    
    typedef std::integral_constant<bool, true> true_type;
    typedef std::integral_constant<bool, false> false_type;
    typedef const_value(1) one;
    
    class unit {
    public:
        float value;
        std::string units;
    public:
        explicit unit(float val,std::string uni=""):units(uni),value(val){};
        unit():units(""),value(0){};
        unit(const unit& u){
            value = u.value;
            units = u.units;
        };
        //virtual unit& operator =(const unit& u) = 0;
        unit&operator=(float val) {
            value = val;
        }
    };
    
    
    void output(std::ostream& os, unit u, true_type, false_type) {
        os << u.value << u.units;
    };
    
    void output(std::ostream& os, unit u, false_type, true_type) {
        os << u.value << u.units;
    };
    
    void output(std::ostream& os, unit u, false_type, false_type) {
        os << u.value;
    }
    
    std::ostream& operator<<(std::ostream& os, unit u){
        output(os, u, type_traits<unit>::__is_length(), type_traits<unit>::__is_time());
        return os;
    }
    
    #endif //WEEK10HM_UNIT_H
    

    然后通过基类来衍生出基本的时间类和长度类second和meter,为了方便,所有的子类都写在meter.h中

    //
    // Created by laixi on 2018/5/28.
    //
    
    #ifndef WEEK10HM_METER_H
    #define WEEK10HM_METER_H
    
    #include "unit.h"
    
    class meter: public unit {
    public:
        meter(float val=0):unit(val,"m"){};
        //meter(unit& u):unit("m"){};
        meter&operator=(const meter& m){
            value = m.value;
        };
        //meter(float val):unit("m"),value(val){};
    };
    
    class kilometer: public unit {
    public:
        kilometer(float val=0):unit(val,"km"){};
        //kilometer(float val):unit("km"),value(val){};
    };
    
    class second: public unit {
    public:
        second(float val=0):unit(val,"s"){};
        //second(float val):unit("s"),value(val){};
    };
    
    class minute: public unit {
    public:
        minute(float val=0):unit(val,"m"){};
        //minute(float val):unit("m"),value(val){};
    };
    
    
    template <class U>
    meter getLengthBase(measurement<U> &m){
        meter me = meter(m.value());
        me.value = me.value * m;
        return me;
    }
    
    template <class U>
    second getTimeBase(measurement<U> &m){
        second se = second(m.value());
        se.value = se.value * m;
        return se;
    }
    
    template <class U, class unit>
    unit base_unit(measurement<U> &m,false_type,false_type){
        return m.getUnit();
    }
    
    template <class U>
    meter base_unit(measurement<U> &m,false_type,true_type){
        return getLengthBase(m);
    }
    
    template <class U>
    second base_unit(measurement<U> &m,true_type,false_type){
        return getTimeBase(m);
    }
    
    template <class U>
    typename type_traits<U>::baseType base_unit(measurement<U> &m,false_type,false_type){
        return m.getUnit();
    }
    
    template <class U>
    typename type_traits<U>::baseType measurement<U>::description() {
        return base_unit(*this,typename type_traits<U>::__is_time(),typename type_traits<U>::__is_length());
    }
    
    template <class U>
    std::ostream& operator<<(std::ostream& os, U u){
        output(os, u, type_traits<U>::__is_length(), type_traits<U>::__is_time());
        return os;
    }
    
    #endif //WEEK10HM_METER_H
    

    最后,在main.cpp中按照题意输入代码,即可运行通过了。

    #include <iostream>
    
    #include "meter.h"
    
    int main() {
        //std::cout << "Hello, World!" << std::endl;
        measurement<meter> m1 = 20;
        measurement<kilometer> m2 = 11.2;
        meter me = m1.description();
    
        measurement<second> m3 = 20;
        measurement<minute> m4 = 10;
    
        measurement<double> m5 = 10;
    
        std::cout << me << std::endl;
        std::cout << m2.description() << std::endl;
        std::cout << m3.description() << std::endl;
        std::cout << m4.description() << std::endl;
        std::cout << m5.description() << std::endl;
        return 0;
    }
    

    运行结果为

    20m
    11200m
    20s
    600s
    10
    

    相关文章

      网友评论

          本文标题:Boolan STL与泛型编程 第五周作业

          本文链接:https://www.haomeiwen.com/subject/drywjftx.html