2

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

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

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

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

4

1 回答 1

6

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

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

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

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

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

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

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

于 2015-11-18T18:07:17.267 回答