Комбинируйте обобщённые и ОО-техники, усиливая их достоинства, но не их недостатки
Причина
Обобщённые и ОО-техники дополняют друг друга.
Пример
Статическое помогает динамическому: используйте статический полиморфизм для реализации динамически полиморфных интерфейсов.
class Command {
// чисто виртуальные функции
};
// реализации
template</*...*/>
class ConcreteCommand : public Command {
// реализовать виртуальные функции
};
Пример
Динамическое помогает статическому: предлагайте обобщённый, удобный, статически связанный интерфейс, но внутри диспетчеризируйте динамически, обеспечивая унифицированную структуру объекта. Примеры включают стирание типов, как в случае с удалителем std::shared_ptr (но не злоупотребляйте стиранием типов).
#include <memory>
class Object {
public:
template<typename T>
Object(T&& obj)
: concept_(std::make_shared<ConcreteCommand<T>>(std::forward<T>(obj))) {}
int get_id() const { return concept_->get_id(); }
private:
struct Command {
virtual ~Command() {}
virtual int get_id() const = 0;
};
template<typename T>
struct ConcreteCommand final : Command {
ConcreteCommand(T&& obj) noexcept : object_(std::forward<T>(obj)) {}
int get_id() const final { return object_.get_id(); }
private:
T object_;
};
std::shared_ptr<Command> concept_;
};
class Bar {
public:
int get_id() const { return 1; }
};
struct Foo {
public:
int get_id() const { return 2; }
};
Object o(Bar{});
Object o2(Foo{});
Примечание
В шаблоне класса не-виртуальные функции инстанцируются только при использовании — но виртуальные функции инстанцируются всегда. Это может раздуть объём кода и чрезмерно ограничить обобщённый тип, инстанцируя функциональность, которая никогда не потребуется. Избегайте этого, даже несмотря на то что фасеты стандартной библиотеки допустили эту ошибку.
Смотрите также
- ref ???
- ref ???
- ref ???
Контроль
Смотрите ссылки на более конкретные правила.
T.concepts: Правила концептов
Концепты — это средство C++20 для задания требований к аргументам шаблона. Они играют ключевую роль в мышлении об обобщённом программировании и лежат в основе большого объёма работ по будущим библиотекам C++ (стандартным и не только).
Этот раздел предполагает поддержку концептов.
Краткое описание правил использования концептов:
- T.10: Задавайте концепты для всех аргументов шаблона
- T.11: Везде, где возможно, используйте стандартные концепты
- T.12: Предпочитайте имена концептов вместо
auto - T.13: Предпочитайте сокращённую запись для простых концептов с одним типовым аргументом
- ???
Краткое описание правил определения концептов:
- T.20: Избегайте «концептов» без содержательной семантики
- T.21: Требуйте полный набор операций для концепта
- T.22: Задавайте аксиомы для концептов
- T.23: Различайте уточнённый концепт и его более общий случай, добавляя новые паттерны использования
- T.24: Используйте классы-теги или трейты для различения концептов, отличающихся только семантикой
- T.25: Избегайте взаимодополняющих ограничений
- T.26: Предпочитайте определять концепты через паттерны использования, а не через простой синтаксис
- ???