Рассмотрим группу фундаментальных типов, Foo
, все с уникальными реализациями общего метода, Bar()
. Я могу комбинировать Foo1
, Foo2
, Foo5
следующим образом:
CombinedFoo<Foo1, Foo2, Foo5> combined_foo;
, который использует рекурсивное наследование, чтобы эффективно комбинировать CombinedFoo с:
class CombinedFoo <Foo1, Foo2, Foo5>
{
Foo1 foo1;
Foo2 foo2;
Foo5 foo5;
public:
void Bar ()
{
foo1.Bar();
foo2.Bar();
foo5.Bar();
}
};
Это удобно , но я сталкиваюсь с проблемой, когда хочу, чтобы функция во время выполнения выбирала, какие Foo
типы объединить для отправки в функцию, скажем template <typename Foo> void Do (Foo && foo);
. Пример решения с if
s и switch
s для решения 3 вариантов варианта:
int result = 0;
if (criteria_for_foo1)
result += 100;
if (criteria_for_foo2)
result += 10;
if (criteria_for_foo3)
result += 1;
switch (result)
{
case 001 : Do(Foo3());
break;
case 010 : Do(Foo2());
break;
case 011 : Do(CombinedFoo<Foo2, Foo3>());
break;
case 100 : Do(Foo1());
break;
case 101 : Do(CombinedFoo<Foo1, Foo3>());
break;
case 110 : Do(CombinedFoo<Foo1, Foo2>());
break;
case 111 : Do(CombinedFoo<Foo1, Foo2, Foo3>());
break;
default : break;
}
Операторы if
хороши, они линейно растут, но оператор switch
экспоненциально растет как У нас есть больше вариантов. У моей реальной проблемы есть 4 варианта, и поэтому мне нужно обработать 16 случаев, которые я бы предпочел не поддерживать.
Я считаю, что нет способа избежать экспоненциального роста исполняемого файла, но есть ли способ избежать этого в коде ( без внесения существенных недостатков в метод Bar
[добавлено из правки])? Или существует известное решение / альтернатива для этой общей проблемы c?
РЕДАКТИРОВАТЬ:
Для ясности: Do(Foo1); Do(Foo2);
не совпадает с Do(CombinedFoo<Foo1, Foo2>())
, и что крайне важно, чтобы Foo
s были объединены для одного вызова Do
.
Для тех, кто ненавидит абстракцию, реальная проблема заключается в оптимизации задачи NP-Hard где мои Foo
с действительно Generator
с фундаментальных Move
с, которые могут редактировать мое решение, это затем отправляется в различные Solver
с, например SolverSimulatedAnnealing
. Если бы мне нужно было отправлять только один генератор за один раз, тогда мои решатели выполняли бы итерации, где они большую часть времени проводили бы в замешательстве (хорошо известно, что такой же тип перемещения неоднократно дает этот эффект).
Причина, по которой у меня проблема с опциями, заключается в том, что некоторые из моих Solver
не могут правильно использовать некоторые из Move
, в зависимости от экземпляра Problem
.