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

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

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

提示

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

   measurement m1 = 20;
   measurement m2 = 11.2;
   meter me = m1.description();

   measurement m3 = 20;
   measurement m4 = 10;

   measurement 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 
#define const_value(x) std::integral_constant

typedef std::integral_constant true_type;
typedef std::integral_constant false_type;
typedef const_value(1) one;

template 
class type_traits {
public:
    typedef false_type __is_time;
    typedef false_type __is_length;
    typedef one coefficient;
    typedef type baseType;
};


template <>
class type_traits {
public:
    typedef false_type __is_time;
    typedef true_type __is_length;
    typedef one coefficient;
    typedef meter baseType;
};

template <>
class type_traits {
public:
    typedef false_type __is_time;
    typedef true_type __is_length;
    typedef const_value(1000) coefficient;
    typedef meter baseType;
};

template <>
class type_traits {
public:
    typedef true_type __is_time;
    typedef false_type __is_length;
    typedef one coefficient;
    typedef second baseType;
};

template <>
class type_traits {
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 measurement {
protected:
    typename type_traits::coefficient coeff;
    U* _unit;

public:
    explicit measurement();
    explicit measurement(const measurement& m);
    measurement operator =(U u);
    measurement operator =(measurement m);
    measurement operator =(float val){
        _unit = new U(val);
    }
    U getUnit() const {return *this->_unit;};
    float value() const {
        return _unit->value;
    };
    typename type_traits::baseType description();
    operator double(){return coeff;};
    measurement(float val){
        _unit = new U(val);
    };
    template 
            measurement operator= (T val){
        if (!_unit) {
            _unit = new U(val);
        } else
            *_unit = val;
    }
};

template
measurement::measurement(const measurement &m) {
    _unit = new U(*m._unit);
}


template
measurement measurement::operator=(U u) {
    if (!_unit) {
        _unit = new U(u);
        return *this;
    }
    if (*_unit != u)
        *_unit = u;
    return *this;
}

template
measurement measurement::operator=(measurement m) {
    if (!_unit) {
        _unit = new U(m.description());
        return *this;
    }
    if (*_unit != m.description())
        *_unit = m.description();
    return *this;
}


template
measurement::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 
#include "measurement.h"

typedef std::integral_constant true_type;
typedef std::integral_constant 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::__is_length(), type_traits::__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 
meter getLengthBase(measurement &m){
    meter me = meter(m.value());
    me.value = me.value * m;
    return me;
}

template 
second getTimeBase(measurement &m){
    second se = second(m.value());
    se.value = se.value * m;
    return se;
}

template 
unit base_unit(measurement &m,false_type,false_type){
    return m.getUnit();
}

template 
meter base_unit(measurement &m,false_type,true_type){
    return getLengthBase(m);
}

template 
second base_unit(measurement &m,true_type,false_type){
    return getTimeBase(m);
}

template 
typename type_traits::baseType base_unit(measurement &m,false_type,false_type){
    return m.getUnit();
}

template 
typename type_traits::baseType measurement::description() {
    return base_unit(*this,typename type_traits::__is_time(),typename type_traits::__is_length());
}

template 
std::ostream& operator<<(std::ostream& os, U u){
    output(os, u, type_traits::__is_length(), type_traits::__is_time());
    return os;
}

#endif //WEEK10HM_METER_H

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

#include 

#include "meter.h"

int main() {
    //std::cout << "Hello, World!" << std::endl;
    measurement m1 = 20;
    measurement m2 = 11.2;
    meter me = m1.description();

    measurement m3 = 20;
    measurement m4 = 10;

    measurement 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与泛型编程 第五周作业)