C++ Policy Based Design
Что я не понимаю в дизайне, основанном на политике Александреску, так это создание новых типов, не имеющих ничего общего, где, на мой взгляд, еще много общего, что должно быть как-то представлено.
Например, 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
не отображается на общедоступном интерфейсе этого класса, он отлично работает...
1 ответ
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
, Важно, чтобы строки можно было передавать по значению и легко копировать.