【问题标题】:C++ Policy Based Design基于 C++ 策略的设计
【发布时间】:2016-02-20 14:06:25
【问题描述】:

我不理解 Alexandrescu 基于策略的设计 是创建没有任何共同点的新类型,在我看来,仍然有很多共同点应该以某种方式表示。

例如,std::stringstd::basic_string<>:分配器是非常内部的东西,在我看来,使用该类的代码不应知道该类正在使用哪个分配器。

但是由于创建了一个新类型,比如说std::basic_string_1,所有那些在std::string& 周围传递的方法基本上都被破坏了,我看不出有一个正当理由为什么std::basic_string<> 有不同的分配器应被视为与带有另一个分配器的std::basic_string<> 完全不同。

我的问题是:为什么每个std::basic_string<> 都没有共同的父母,这样就可以避免这个问题?通常在我的代码中,当我有一个Whatever<T> 时,我让它继承自某种WhateverBase,并且当T 没有显示在该类的公共界面上时,它可以很好地工作......

【问题讨论】:

  • 如果您需要运行时多态分配器支持,您可以使用std::experimental::polymorphic_allocator
  • 您可以避免一些问题,但不可避免地会产生一些其他问题。这是一种权衡。

标签: c++ string templates stdstring policy-based-design


【解决方案1】:

分配器是非常内部的东西,在我看来,使用该类的代码不应知道该类正在使用哪个分配器。

这就是为什么您通常不在乎,只需使用std::string。大多数代码不使用自定义分配器,所以这根本不是问题。

正如 Kerrek SB 在评论中指出的那样,您可以选择使用std::experimental::pmr::string,它使用类型擦除的分配器,因此隐藏了使用哪种分配器的详细信息。这有一些运行时成本,但也有一些优势。

更一般地说,您是对的,基于策略的设计会导致无法互操作的不同类型的爆炸式增长。有时这是一个问题(有时不是)。处理这个问题的一种方法是编写通用代码,不管它是处理policy_base_ptr<X, Y, Z> 还是policy_based_ptr<A, B, C>。编写使用“某种智能指针”的通用代码,而您并不关心确切的类型。但这并不总是一种选择,例如在定义接口时,您经常需要使用具体类型。

我的问题是:为什么不是每个std::basic_string<> 都有共同的父母,这样就可以避免这个问题?一般来说,在我的代码中,当我有一个Whatever<T> 时,我让它继承自某种WhateverBase,当T 没有显示在该类的公共界面上时,它工作得很好......

这意味着你的类是多态的,只知道基类的代码必须通过引用传递它。它不能按值传递,因为它会被切片。这意味着您必须小心对象所有权,并关心引用何时仍然有效,以及谁负责销毁派生类型。

这是您在自己的软件中做出的完全合理的选择,但不适用于像std::string 这样的通用词汇类型。字符串可以按值传递并轻松复制,这一点很重要。

【讨论】:

  • 我看到了通用基类的缺点。那么分配器的公共基类怎么样,当需要不同的行为时在对象构造中传递,以便分配器是一个多态对象,由传递的实例拥有,而 std::string 保持原样? (PS 我还想澄清 std::string 只是一个例子,这个问题更普遍地是基于策略的设计,所以如果你愿意,如果你认为任何容器会产生更好的例子)
  • 是的,这正是en.cppreference.com/w/cpp/experimental/polymorphic_allocator 的含义(您现在已经被指向了三次 :-)
猜你喜欢
  • 2014-09-30
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-03
相关资源
最近更新 更多