在Alexandrescu 基于策略的设计中我不理解的是创建了没有任何共同点的新类型,在我看来,仍然存在许多应该以某种方式表示的共同点。
例如,std::string
和std::basic_string<>
:allocator是非常内部的东西,在我看来,使用该类的代码不会知道该类正在使用哪个分配器。
但是因为创建了一个新类型,让我们说std::basic_string_1
,所有传递std::string&
的方法基本上都被破坏了,我看不到具有不同分配器的std::basic_string<>
被认为与具有另一个分配器的std::basic_string<>
完全不同的正当理由。
我的问题是:为什么每个std::basic_string<>
都没有共同的父母,所以可以避免这个问题?通常在我的代码中,当我有Whatever<T>
时,我会从某种类型的WhateverBase
继承,当T
没有显示在该类的公共接口上时,它可以很好地工作...
答案 0 :(得分:6)
allocator是非常内部的东西,在我看来,使用该类的代码不应该知道该类正在使用哪个分配器。
这就是为什么通常你不在乎,只需使用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
这样的通用词汇类型。必须能够按值传递字符串并轻松复制。