C++ C++;基于策略的设计

C++ C++;基于策略的设计,c++,string,templates,stdstring,policy-based-design,C++,String,Templates,Stdstring,Policy Based Design,在Alexandrescu基于策略的设计中,我不理解的是没有任何共同点的新类型的创建,在我看来,仍然有许多共同点应该以某种方式表现出来 例如,std::string和std::basic_string:分配器是非常内部的东西,在我看来,使用该类的代码应该不知道该类正在使用哪个分配器 但是由于创建了一个新类型,比如说std::basic_string_1,所有传递std::string&的方法基本上都被破坏了,我看不出一个有效的理由,为什么使用不同分配器的std::basic_字符串与使用另一分配

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

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

但是由于创建了一个新类型,比如说
std::basic_string_1
,所有传递
std::string&
的方法基本上都被破坏了,我看不出一个有效的理由,为什么使用不同分配器的
std::basic_字符串
与使用另一分配器的
std::basic_字符串
完全不同

我的问题是:为什么每个
std::basic_string
都没有公共父级,这样就可以避免这个问题?一般来说,在我的代码中,当我有一个
Whatever
时,我使它继承某种
WhateverBase
,当
T
未显示在该类的公共接口上时,它工作得非常好

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

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

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

更一般地说,基于策略的设计会导致不可互操作的不同类型的激增,这是正确的。有时这是个问题(有时不是)。处理这一问题的一种方法是编写通用代码,而不管它是处理
基于策略的ptr
还是
基于策略的ptr
。编写使用“某种智能指针”的通用代码,而不关心确切的类型。不过,这并不总是一个选项,例如,在定义接口时,通常需要使用具体类型

我的问题是:为什么每个
std::basic_string
都没有公共父级,这样就可以避免这个问题?一般来说,在我的代码中,当我有一个
Whatever
时,我使它继承某种
WhateverBase
,当
T
未显示在该类的公共接口上时,它工作得非常好

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


对于您自己的软件来说,这是一个非常合理的选择,但不适合像
std::string
这样的通用词汇表类型。字符串可以通过值传递并易于复制,这一点非常重要。

如果需要运行时多态分配器支持,可以使用。这样可以避免一些问题,并不可避免地创建一些其他问题。这是一种折衷。我看到了普通基类的缺点。那么,当需要不同的行为时,分配器的公共基类在对象构造上传递,这样分配器就是实例拥有的多态对象,在实例中传递时std::string保持原样,又如何呢?(另外,我还想澄清一下,std::string只是一个例子,问题更一般地说是基于策略的设计,所以如果你愿意,你可以转而谈论任何容器,如果你认为它会成为一个更好的例子)是的,这正是(你现在已经被指了三次:-)