STL分析-准备工作<二>

本文探讨了泛型技术在编程中的应用,特别是在处理类型参数化时如何通过Trait技术简化代码,实现对基本类型和自定义类型的通用处理,以及如何通过Trait技术在不同场景下灵活扩展类型支持,遵循面向对象设计原则,对扩展开放,对修改关闭。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在泛型技术中,类型参数化实现了泛的含义,那么在具体使用中,光有泛是不行的,同样一个泛型函数中,基本类型能和自定义类型完全一致吗,指针能和具体类型一致吗,常量引用和常量指针呢,代码总要落在实处,类型总要具体化,怎么办?我们又不能总是特化,特化太多,模板就失去意义。

在我们面向对象的设计中,我们针对接口编程,用具体的类的对象实现了特例,移动这个接口,2条腿和4条腿以及长翅膀的都有不同实现。

那么在泛型技术中,答案就是Trait技术,Policy技术

类有属性(即数据)和操作两个方面。同样模板也有自己的属性,类型正是模板属性之一

举个例子,在 iostream库中,streambuf的接口依赖EOF的值,在传统的库中,EOF是int

 class streambuf {
    ...
    int sgetc();  // return the next character, or EOF.
    int sgetn(char*, int N);  // get N characters.
  };

如果我们想把它泛型话,我不仅要对char泛型话,还要针对EOF

 template <class charT, class intT>
  class basic_streambuf {
    ...
    intT sgetc();
    int sgetn(charT*, int N);
  };

这样问题就来了,用户其实不用该关心EOF。我们要想办法把多余的参数化类型去掉,这就是我们所说的Trait的用武之地。

我们先定义一个模板

 template <class charT>
  struct ios_char_traits { };

我们先定义个空实现作为默认的,针对具体的字符类型,我们可以特化以提供有用的语义。

struct ios_char_traits<char> {
    typedef char char_type;
    typedef int  int_type;
    static inline int_type eof() { return EOF; }
  };



我们并没有对 ios_char_traits<char> 定义任何数据成员

现在,我们的 basic_streambuf 是这个样子的

template <class charT>
  class basic_streambuf {
    public:
      typedef ios_char_traits<charT> traits_type;
      typedef traits_type::int_type int_type;
      int_type eof() { return traits_type::eof(); }
      ...
      int_type sgetc();
      int sgetn(charT*, int N);
  };
这样我们的新模板类消除了没有用的模板参数,其他的部分和前面都很类似,编译器自己在Traits中寻找类型

如果这个流要支持新的类型,我们只要定义一个新的ios_char_traits

 struct ios_char_traits<wchar_t> {
    typedef wchar_t char_type;
    typedef wint_t  int_type;
    static inline int_type eof() { return WEOF; }
  };

trait在把基本类型传人模板和一些不支持模板的某些调用的类型时特别有用,这也实现了一个面向对象设计原则中的一条,对扩展开放,对修改关闭。你肯定没发对基本类型做修改,也无法对有限制修改的库做修改,这时你就该考虑,trait

使用triat技术在我们一个数值分析库中,我们可能这样支持泛型话


  template <class numT>
  struct float_traits { };

  struct float_traits<float> {
    typedef float float_type;
    enum { max_exponent = FLT_MAX_EXP };
    static inline float_type epsilon() { return FLT_EPSILON; }
    ...
  };

  struct float_traits<double> {
    typedef double float_type;
    enum { max_exponent = DBL_MAX_EXP };
    static inline float_type epsilon() { return DBL_EPSILON; }
    ...
  };

这样我们可以在不知道具体类型是float还是double或者是自定义类型的情况下使用 "max_exponent"。

template <class numT>
  class matrix {
    public:
      typedef numT num_type;
      typedef float_traits<num_type> traits_type;
      inline num_type epsilon() { return traits_type::epsilon(); }
      ...
  };






                
raw_data <- readxl::read_excel("C:/Users/Lenovo/Desktop/货币供应量月.xlsx", sheet = "货币供应量月") clean_data <- raw_data clean_data <- rename( raw_data, date = `时间`, m2_value = `货币和准货币(M2)供应量期末值(亿元)`, m2_growth = `货币和准货币(M2)供应量同比增长(%)`, m1_value = `货币(M1)供应量期末值(亿元)`, m1_growth = `货币(M1)供应量同比增长(%)`, m0_value = `流通中现金(M0)供应量期末值(亿元)`, m0_growth = `流通中现金(M0)供应量同比增长(%)` ) clean_data_v1 <- clean_data %>% arrange(date) clean_data <- clean_data %>% mutate( year = year(date), month = month(date), month_label = factor(month.abb[month], levels = month.abb) ) %>% drop_na() glimpse(clean_data)数据清洗 Browse[8]> glimpse(clean_data) Rows: 295 Columns: 14 $ date <dttm> 2000-06-01, 2000-07-01, 2000-08-01, 200… $ m2_value <dbl> 124486.8, 124192.8, 125673.3, 128352.6, … $ m2_growth <dbl> 13.7, 13.4, 13.3, 13.4, 12.3, 12.4, 12.3… $ m1_value <dbl> 48024.40, 47803.09, 48885.38, 50616.89, … $ m1_growth <dbl> 23.7, 22.6, 21.9, 20.8, 18.2, 17.1, 16.0… $ m0_value <dbl> 13006.04, 13156.47, 13378.68, 13894.69, … $ m0_growth <dbl> 19.5, 17.5, 17.4, 13.4, 11.8, 11.2, 8.9,… $ year <dbl> 2000, 2000, 2000, 2000, 2000, 2000, 2000… $ month <dbl> 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6… $ month_label <fct> Jun, Jul, Aug, Sep, Oct, Nov, Dec, Jan, … $ m0_prev <dbl> NA, 13006.04, 13156.47, 13378.68, 13894.… $ m0_mom <dbl> 0.648349827, 1.156616464, 1.688978883, 3… $ spring_dummy <dbl> 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, … $ scissors_gap <dbl> 10.0, 9.2, 8.6, 7.4, 5.9, 4.7, 3.7, 3.3,… Browse[8]>
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值