Является ли использование посетителя с пустым хранилищем интерфейса разумным способом выявления специфических для реализC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Является ли использование посетителя с пустым хранилищем интерфейса разумным способом выявления специфических для реализ

Сообщение Anonymous »

Я проектирую API C ++, где: < /p>

[*] Клиенты когда -либо используют только основной интерфейс признака (

Код: Выделить всё

main_trait
).
[*] Каждая конкретная реализация main_trait имеет выделенный интерфейс метрик (

Код: Выделить всё

metrics_trait
) exposing runtime statistics.
[*]I provide a default visitor that extracts metrics into a type-safe storage object, so clients don’t need to know the implementation details.
Users can optionally implement their own main_trait + metrics_trait + metrics_visitor + storage if they want a custom поведение. < /li>
< /ul>
Вот соответствующие эскизы интерфейса: < /p>

Код: Выделить всё

class storage {}; // empty interface-ish

class metrics_trait {
public:
virtual ~metrics_trait() = default;
virtual std::vector serialize() = 0;
virtual void visit(const std::function&) = 0;
virtual void visit(class metrics_visitor* visitor) = 0;
};

class main_trait {
public:
virtual ~main_trait() = default;
virtual metrics_trait* get_metrics() = 0;
};

class metrics_visitor {
public:
virtual ~metrics_visitor() = default;
virtual void visit(metrics_trait* m) = 0;
virtual storage* get_storage() = 0;
};

< /code>
Для реализации по умолчанию: < /p>
struct storage_impl : storage {
const int member1;
const double member2;
storage_impl(int m1, double m2) : member1(m1), member2(m2) {}
};

class metrics_visitor_impl : public metrics_visitor {
storage_impl* m_storage;
public:
void visit(metrics_trait* m) override { /* builds storage_impl */ }
storage_impl* get_storage() override { return m_storage; }
};

< /code>
клиенты могут затем сделать: < /p>
metrics_trait* metrics = main_trait_instance->get_metrics();
auto* visitor = new metrics_visitor_impl();
metrics->visit(visitor);
auto* s = visitor->get_storage();
std::cout member1 
Первоначально я остановился на этом дизайне: < /p>
metrics->visit([](const std::string& name, const std::any& value) {
if (name == "member1") { … }
});

< /code>
Но это заставляет кого -либо извлекать метрики, чтобы узнать все строки впереди, что является хрупким. main_trait 
, они также могут легко подключить свои собственные метрики // Трио без нарушения существующего кода.
Вот MRE, готовый к Godbolt, который работает очень хорошо
Вопрос:
Из современного конструкции API-дизайна:

использует плюс. Познакомясь с метриками, привязанными к конкретной реализации? совместимость.
Это может быть до C ++ 23.
спасибо

Подробнее здесь: https://stackoverflow.com/questions/797 ... -expose-im
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»