У меня есть семейство параметризованных функций, типа:
template
Мне требуется во время исполнения выбирать одну из специализаций шаблона нужной функции в зависимости от внешнего параметра (разумеется, все соответствующие специализации должны быть определены во время компиляции).
В очень примитивной реализации это выглядит так:
template class F>
void *choose_from(void *arg, char run_time_type_of_arg) {
switch (run_time_type_of_arg) {
case 'i': return F
Вызывается это очень удобно:
void *test_some_func(void *arg, char run_time_type_of_arg) {
return choose_from
Но меня категорически не устраивает отсутствие расширяемости/гибкости, жестко прописанные в коде кейсы и отсутствие возможности задавать разный набор специализаций для разных функций.
Поэтому я хочу переписать эту конструкцию с использованием type traits и более общих шаблонов на их основе:
template
template class F, typename T1>
struct ChooseFrom1 {
inline static void *call(void *arg, char run_time_type_of_arg) {
if (run_time_type_of_arg == TypeTrait
template class F, typename T1, typename T2>
struct ChooseFrom2 {
inline static void *call(void *arg, char run_time_type_of_arg) {
if (run_time_type_of_arg == TypeTrait
За счет встраивания функций все вызовы полностью удаляются на этапе компиляции, и в результате получается машинный код, почти полностью идентичный первой реализации на switch/case (я проверял листинги - все так).
Но у меня не получилось рекурсивного шаблона (как видно ChooseFrom1 и ChooseFrom2 имеют разные имена).
Вызывать это можно, например, так (совершенно не удобно):
void *test_some_func_2(void *arg, char run_time_type_of_arg) {
auto a = ChooseFrom1
В идеале я хочу получить один общий шаблон, который можно было бы вызывать так:
void *test_some_func_ideal(void *arg, char run_time_type_of_arg) {
return ChooseFrom
Но все попытки совместить ChooseFrom1 и ChooseFrom2 ... ChooseFromN в один рекурсивный шаблон (один обобщенный шаблон для самой рекурсии плюс одна его специализация для остановки рекурсии) наталкиваются на ошибки компиляции.
Буду благодарен за любые советы по реализации данной идеи или обоснование теоретической невозможности подобной реализации.
Ответ
Возможно, вам нужно это:
template class F, typename... Types>
struct ChooseFrom
{
};
template class F, typename T1, typename... TRest>
struct ChooseFrom
template class F>
struct ChooseFrom
С другой стороны, я бы на вашем месте постарался не доводить до передачи типа через эмуляцию typeid в рантайме, а протянуть тип как параметр шаблона в программе. При этом можно было бы по идее обойтись вовсе без ChooseFrom, и использовать прямо SomeFunc
Комментариев нет:
Отправить комментарий