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

设计一个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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容