2014-10-29 4 views
3

Я довольно новичок в C++, и я пытаюсь добиться чего-то немного сложного, для которого я не могу найти подходящего решения.Создание экземпляра шаблона и выбор функции во время выполнения

Скажем, у меня есть эти две функции:

template <class T1, class T2> void foo(T1 param1, T2 param2){...}; 
template <class T1, class T2> void bar(T1 param1, T2 param2){...}; 

И во время выполнения, я хочу, чтобы выбрать на этих двух функций, и создать его экземпляр с некоторыми типами шаблонов, полученных из пользовательского ввода, скажем полукокса c , Так что я мог бы сделать что-то вроде:

double d; 
float f; 
switch(c) { 
    case 'a': 
     foo(d, f); break; 
    case 'b': 
     foo(f, d); break; 
    case 'c': 
     bar(d, f); break; 
    case 'd': 
     bar(f, d); break; 

Но это решение некрасиво, не масштабируется (я хочу, чтобы иметь возможность добавить больше функций и больше параметров шаблона) и т.д. А также, я не могу видеть, способ присвоить одну из функций foo или bar указателю функции, поскольку параметры шаблона неизвестны до выполнения.

Так что если кто-то может предоставить мне хорошее, чистое решение этой проблемы, я был бы очень счастлив! Приветствия.

Редактировать Позвольте мне пояснить несколько вещей.

Я доступа двоичные файлы, в которых данные могут быть сохранены как floats или doubles. Очевидно, что программа не знает этого типа, поэтому пользователь должен каким-то образом указать ее.

Затем некоторые математические вычисления должны выполняться на данных, загружаемых из файла. И возможно несколько таких вычислений, представленных выше функциями foo и bar.

Так что я хотел бы, чтобы пользователь имел возможность указать тип данных в файле во время выполнения, а затем выберите функцию, чтобы применить к загруженным данным во время выполнения слишком. switch(c) был просто иллюстрацией того, как я думал, что пользователь может выбрать такие вещи.

+0

вы можете дать некоторый фон на том, что это вы пытаетесь достичь? –

+0

Что такое шаблон, которому должны следовать вызовы (по отношению к 'c')? – Columbo

+0

Шаблоны не работают во время выполнения. Вы можете создать 'unordered_map ' и вызвать это на основе ключа. –

ответ

1

Вы не можете принимать указатели на функциональные шаблоны, потому что они не являются функциями, но должны быть созданы ранее. Вы можете получить такой указатель:

typedef void (*Tfkt_int_int)(int, int); 
Tfkt_int_int Ptr = &foo<int,int>; 

Как вы можете видеть, вам необходимо указать возможные комбинации типов.

Если вас интересует более чистый код, вы можете поместить все функции, которые используют одну и ту же подпись на одной карте. (То есть, вам нужна одна карта на подпись.) Затем различайте, какую карту использовать в инструкции switch.

std::map<char, Tfkt_int_int> Map_int_int; 
Map_int_int['a'] = &foo<int,int>; 
Map_int_int['b'] = &bar<int,int>; 
// more ... 

typdef void (*Tfkt_int_double)(int, double); 
std::map<char, Tfkt_int_double> Map_int_double; 
Map_int_double['a'] = &foo<int,double>; 
Map_int_double['b'] = &bar<int,double>; 
// more ... 

Если вы хотите только одну карту, и готовы пожертвовать типа savety, вы можете бросить вокруг типов параметров. Это может быть не столько потеря в вашей ситуации, поскольку вы уже читали эти данные из байтового потока.

template <class T1, class T2> void foo(char* param1, char* param2) 
{ 
    T1 P1 = *(reinterpret_cast<T1*>(param1)); 
    T2 P2 = *(reinterpret_cast<T2*>(param2)); 
    // ... 
}; 

typedef void (*Tfkt)(char*, char*); 
std::map<char, Tfkt> Map; 
Map['a'] = &foo<int,int>; 
Map['b'] = &foo<int,double>; 
// more ... 

Тогда зови как:

double d; 
int i; 
char c = 'b'; 
(*(Map[c]))(reinterpret_cast<char*>(&i), reinterpret_cast<char*>(&d)); 
+0

Ваш ответ действительно помог мне решить мою проблему, хотя я точно не реализовал ее таким образом. Благодаря! – dranitou

Смежные вопросы