Код: Выделить всё
void dispatch(const Buffer& buffer)
{
switch (buffer.getId())
{
case Id::Type1:
{
Type1 obj;
obj.deserialize(Buffer);
// ... other code to print and process the buffer
}
break;
case Id::Type2:
{
Type2 obj;
obj.deserialize(Buffer);
// ... same code to print and process the buffer as above
}
break;
// ... and again, and again... for 10 to 30 types, depending on context
}
- мы не можем контролировать Type1, Type2... поэтому мы не можем играть с их иерархией или интерфейсами. В некотором контексте эти типы наследуются от общего базового класса (слишком общего, чтобы быть полезным), но вы можете эффективно рассматривать их как несвязанные типы в рамках этой проблемы.
- код выполнение в каждом случае фактически одинаково, если вы видите все, что связано с типами, как данные, к которым вы можете получить доступ через идентификатор.
- все типы и идентификаторы полностью известны и будут известны во время компиляции. Это кажется очевидным, но я предпочитаю это объяснить.
Теперь предположим, что у меня есть некоторый шаблонный obj_type_t, который "возвращает" тип, соответствующий идентификатору (как это построить, будет темой другого вопроса), и давайте сосредоточимся на случае переключения.
Мой решения
Мой простой подход заключался в использовании рекурсии шаблона для автоматического создания случая переключения:
Код: Выделить всё
// Base case
template
void generateSwitch(T i, std::integer_sequence, Predicate&& predicate, DefaultPredicate&& defaultPredicate)
{
defaultPredicate();
}
// Recursive step
template
void generateSwitch(T i, std::integer_sequence, Predicate&& predicate, DefaultPredicate&& defaultPredicate)
{
if (i == First)
{
predicate(First);
}
else
{
generateSwitch(i, std::integer_sequence{}, predicate, defaultPredicate);
}
}
Код: Выделить всё
void dispatch(const Buffer& buffer)
{
auto processBuffer = [buffer](auto Id) // this auto is actually an integral_constant, so it's ok to use it as a template parameter
{
obj_type_t obj;
obj.deserialize(buffer);
// other code to print and process the buffer
};
auto invalidId = [](){ std::cout
Подробнее здесь: [url]https://stackoverflow.com/questions/79145159/compile-time-generated-switch-case-with-no-performance-hit[/url]