基于 C++ 策略的设计

C++ Policy Based Design

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

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

但是由于创建了一个新类型,假设 std::basic_string_1,所有那些传递 std::string& 的方法基本上都被破坏了,我看不出一个有效的理由具有不同分配器的 std::basic_string<> 应被视为与具有另一个分配器的 std::basic_string<> 完全不同。

我的问题是:为什么不是每个std::basic_string<>都有共同的父节点,这样就可以避免这个问题?通常在我的代码中,当我有一个 Whatever<T> 时,我让它继承自某种 WhateverBase,并且当 T 没有显示在那个 public 界面上时=30=],效果很好...

allocator are something very internal and, in my opinion, the code using that class shall not be aware of which allocator that class is using.

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

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

更一般地说,您是对的,基于策略的设计会导致无法互操作的不同类型的激增。有时这是一个问题(有时不是)。处理该问题的一种方法是编写不关心处理 policy_base_ptr<X, Y, Z> 还是 policy_based_ptr<A, B, C> 的通用代码。编写使用 "some kind of smart pointer" 的通用代码,您不关心确切的类型。但这并不总是一个选项,例如在定义接口时,您经常需要使用具体类型。

My question is: why there is not common parent for every std::basic_string<>, so that this problem could be avoided? Generally in my code when I have a Whatever<T>, I make it inherits from a WhateverBase of some sort, and when T is not shown on the public interface of that class, it works greatfully...

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

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