Трябва да заменя динамичния полиморфизъм в код с доста големи класове и имам проблеми с дизайна на CRTP + променливи шаблони.
За да илюстрирам, предоставям проблем с играчка по-долу.
Има динамично полиморфен клас, който използва следния интерфейс:
int main() {
Loop loop;
Add add ;
loop.set(add);
loop.run();
Sub sub ;
loop.set(sub);
}
Разбира се, Sub
и Add
са извлечени от базов клас Operation
, а op(double & v)
е виртуален метод.
Трябва да запазя този интерфейс по други причини, докато променям динамичния чрез статичен полиморфизъм, това е моето решение до момента:
template <typename T> class Operation {
public:
double d=1.;
void op(double & d) { static_cast<T*>(this)->op(d);}
};
class Add final: public Operation<Add> {
public: void op(double & v) { v += d; }
};
class Sub final: public Operation<Sub> {
public: void op(double & v) { v -= d; }
};
и за клас Loop
:
template <typename... Types>
class MetaLoop {
public:
double d = 0 ;
template <typename T> void set(T & t) {
std_cxx17::get<std::vector<T*> >(data).push_back(&t) ;
}
template <typename T> void run() {
for (auto j = 0; j<2E9 ; ++j)
std_cxx17::get<std::vector<T*> >(data).back()->op(d);
std::cout << d << std::endl;
}
private:
std::tuple<std::vector<Types*>... > data ;
};
typedef MetaLoop<Add,Sub> Loop ;
std_cxx17::get<T*>(data)
е извикване на метод, избиращ елементи в кортеж по тип, подобно на тази публикация
Това решение обаче изисква почти интерфейса, който искам, с изключение на необходимостта от предоставяне на аргумента на шаблона на run()
, т.е. run<Add>
и run<Sub>
и необходимостта от регистриране Add
и Sub
на MetaLoop
в typedef MetaLoop<Add,Sub> Loop
Бих искал да знам дали е възможно, без да използвам макроси, да:
- Регистрирайте
Operation<T>
класовете вMetaLoop
автоматично (т.е. автоматично извикване наtypedef Metaloop<...operations...>
) - Избягвайте да предоставяте шаблонния клас на метода
run
. (т.е. обадете се наrun()
вместо наrun<Add>()
) - Вземете тези методи от библиотека: Няма ли библиотека (напр. Boost), която може да осигури този вид полиморфизъм статично?
Моля, имайте предвид, че съм наясно, че има няколко други архитектури, които мога да използвам, но има много други ограничения, с които трябва да си играя. Това е просто проблем с играчката за пример.
Благодаря предварително!
РЕДАКТИРАНЕ 1:
Въпрос 2 е отговорен! Вижте тук: http://coliru.stacked-crooked.com/a/e68ea7faabba3e40
Поздравления за https://www.reddit.com/user/17b29a
Add
? Трябва ли да работи кактоAdd
, така иSub
? - person skypjack   schedule 26.09.2016Add
например. - person Astor   schedule 26.09.2016Add
, в който случай ще трябва да сравня, преди да изпълняrun()
. Надявам се, че все още може да се изпълнява статично. - person Astor   schedule 26.09.2016