设计一个Measurement计量单位类型,满足如下要求,
- 当为距离单位,当构造米或者千米等不同距离单位的实例时,统一以米为基本单位,实例调用description函数返回单位对应的meter类型(米类型)
- 当为时间单位,当构造分钟或者秒为单位的实例时,统一以秒为基本单位,实例调用description函数返回单位对应的second类型(秒类型)
- 如果为除距离和时间的其他单位,都打印值即可。
提示
请使用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