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, Важно, чтобы строки можно было передавать по значению и легко копировать.

Другие вопросы по тегам