Méthode variadic en parametre d'une méthode template
Bonjour à tous,
Je suis en train de faire un test simple de capture d'une fonction par une autre.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| template<typename ResultType, typename ParameterType1>
void CaptureMethod(ResultType(*func)(ParameterType1)) {
}
template<typename ResultType, typename ParameterType1, typename ParameterType2>
void CaptureMethod(ResultType(*func)(ParameterType1, ParameterType2)) {
}
template<typename ResultType, typename ParameterType1, typename ParameterType2, typename ParameterType3>
void CaptureMethod(ResultType(*func)(ParameterType1, ParameterType2, ParameterType3)) {
}
int f1(int) { return 0; }
int f2(int, int) { return 0; }
int f3(int, int, int) { return 0; }
int main()
{
CaptureMethod(f1);
CaptureMethod(f2);
CaptureMethod(f3);
return 0;
} |
Ça c'est la version à l'ancienne, le truc c'est qu'il faut que je créer autant de surcharge que le nombre max de paramètre de la méthode que je veux capturer. Donc je me suis dit autant passer par les template variadic:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| template<typename ResultType, typename... ParametersTypes>
void CaptureMethod(ResultType(*func)(ParametersTypes...)) {
}
int f1(int) { return 0; }
int f2(int, int) { return 0; }
int f3(int, int, int) { return 0; }
int f10(int, int, int, int, int, int, int, int, int, int) { return 0; }
int main()
{
CaptureMethod(f1);
CaptureMethod(f2);
CaptureMethod(f3);
CaptureMethod(f10);
return 0;
} |
Maintenant j'aimerais pouvoir capturer des fonctions qui ont un nombre de paramètres variables:
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| template<typename ResultType, typename... ParametersTypes>
void CaptureMethod(ResultType(*func)(ParametersTypes...)) {
}
int fVariable(...) { return 0; }
int main()
{
CaptureMethod(fVariable);
return 0;
} |
Mais là ça ne compile pas (je suis sous Visual 2017). Est-ce possible de capturer une fonction à nombre de paramètres variables? J'avoue que là je n'ai pas trop d'idées.
Pour éviter de devoir donner le type de retour en paramètre template
Notes d'ailleurs qu'il y a moyen d'éviter le type de retour comme paramètre template, à condition de prendre certaines décisions, et de s'y tenir.
Par exemple, nous pourrions décider que le type de retour de la fonction sera toujours le type du premier paramètre reçu, et partir sur quelque chose comme
Code:
1 2 3 4 5 6
|
template <typename RT, typename ... Args>
struct ReturnTypeExtractor{
using returnType = RT;
using functionType = std::function<returnType(returnType, Args ...)>;
}; |
Nous n'aurions alors plus qu'à modifier la liste template de CaptureMethod pour lui donner une forme proche de
Code:
1 2 3 4 5 6 7 8
|
template < typename ... Args,
typename Fun=typename ReturnTypeExtractor<Args ...>::functionType,
typename RT= typename ReturnTypeExtractor<Args ...>::returnType >
RT CaptureMethod(Fun fun, Args ... args ){
return fun(args ...);
} |
ce qui nous permettrait de l'appeler sous les formes proches de
Code:
1 2 3 4 5 6 7 8 9 10
| int f1(int i) { return i; }
int f2(int i, int j) { return i+j; }
int f3(int i, int j, int k) { return i+j+k; }
int main(){
std::cout<<"f1 :"<< CaptureMethod(f1, 1)<<"\n"
<<"f2 :"<<CaptureMethod(f2,1,2)<<"\n"
<<"f3 :"<<CaptureMethod(f3,1,2,3)<<"\n";
return 0;
} |
Avoues que c'est chouette, les templates, non :question: