2011-02-16 3 views
0

Est-il en quelque sorte possible de refléter le type de l'argument d'une fonction au moment de la compilation?Déterminer le type d'argument

Alors que

int b = add(3, 6) 

entraînerait une instanciation de modèle sous la forme de

int add(int a, int b) { return a + b } 

sur un certain modèle de fonction cependant déclaré

A add(A a, B b) { return a + b } 

Je ne sais pas si cela est possible avec les templates, ils ne semblent pas vraiment faits pour la méta-programmation lourde.

+0

Points-virgules manquants dans la question, les réponses, partout. – aschepler

+0

La dernière instruction n'est pas vraie. Il y a même une bibliothèque de programmation de méta modèle complète dans Boost. Les modèles sont merveilleux pour la programmation de méta. – Xeo

+0

@aschepler: les points-virgules sont la chose la plus superflue en C++ – nils

Répondre

0

modèles font tout leur magie au moment de la compilation, mais qui semble être tout à fait suffisant pour ce que vous vous demandez:

template <class T> 
T add(T a, T b) { return a + b; } 

Cela fait un peu plus complexe lorsque les deux peuvent ne pas correspondre, si (par exemple) vous pouvez ajouter un int à un double et obtenir un résultat double.La norme actuelle ne supporte pas vraiment cela ; avec C++ 0x, vous pouvez regarder dans auto et decltype pour de telles tâches.

Bien que Boost typeof fasse souvent le travail.

+0

J'aurais dû être un peu plus précis avec ma question, probablement auto c'est ce que je recherche. Ou puis-je d'une autre manière imbriquer des modèles? J'ai une classe modélisée et je veux qu'une méthode ait un argument Template supplémentaire. 'template classe Vecteur;' and later 'template Vecteur Vecteur :: opérateur + (const ScalarType & scalaire) const' ne fonctionne pas vraiment . – nils

+1

@nils: Cela fonctionnerait, sauf qu'une méthode de template dans une classe template prendrait deux mots-clés 'template':' template template Vecteur Vector :: operator + (const ScalarType & scalar) const' – UncleBens

+0

merci, ça marche – nils

3
template<typename T> 
T add(T a, T b) { return a + b; } 

vous pouvez appeler cela avec tout type intégré (int, court, double, flotteur, etc.), et il instancier la fonction add au moment de la compilation, selon le type que vous utilisez.

Notez que si vous cela en tête divisez/source, vous aurez du mal:

add.h:

template<typename T> 
T add(T a, T b); 

add.cpp:

template<typename T> 
T add(T a, T b) { return a + b; } 

main.cpp:

#include "add.h" 

int a = 3; 
int b = 5; 
int i = add(a, b); 

Lorsque vous essayez de c ompile cela, il va échouer au moment de la liaison. Voici pourquoi.

add.obj ne fait Compiler pas instancier la méthode du modèle add - parce qu'il n'a jamais appelé à add.cpp. La compilation main.obj instancie la déclaration de fonction - mais pas le corps de la fonction. Donc, au moment de la liaison, il ne parviendra pas à trouver la définition de la méthode add.

solution est de Simplest mettre tout l'ensemble de la fonction de modèle dans l'en-tête:

add.h:

template<typename T> 
T add(T a, T b) { return a + b; } 

et vous ne même pas besoin du fichier add.cpp du tout.

3

Cela ne fait-il pas ce que vous demandez?

template <typename A, typename B> 
A add(A a, B b) { return a + b; } 

Ceci est difficilement "lourd méta-programmation".

1

C'est exactement ce que font les modèles. Permettre deux types différents devient un peu plus compliqué mais est également possible.

1

Si vous prévoyez d'utiliser autre chose que des types simples que vous voulez (dans un fichier d'en-tête):

template <typename A> 
inline A add(const A& a, const A& b) { return a + b; } 

Notez la « ligne ».

Comme indiqué par d'autres, le problème avec les types mixtes est comment déterminer le type de retour à partir des types d'argument. Supposons que nous nous en tenions à des types simples et que:

modèle en ligne A ajouter (A a, B b) {return a + b; }

Ensuite, cela ne fonctionne pas (probablement avec seulement un avertissement):

double d = add(1, 1.5); // Sets d to 2.0 

Donc, vous devez faire un certain travail. Par exemple:

template<class A, class B> 
struct Promote 
{ 
}; 

template<class A> 
struct Promote<A,A> 
{ 
    typedef A Type; 
}; 

template<> 
struct Promote<int, double> 
{ 
    typedef double Type; 
}; 

template<> 
struct Promote<double, int> 
{ 
    typedef double Type; 
}; 

La fonction add devient:

template<class A, class B> 
inline typename Promote<A,B>::Type add(A a, B b) 
{ 
    return a + b; 
} 

Ce que tout cela fait pour vous est de vous assurer que le type de retour est celui vous spécifiez pour ajouter une paire donnée de types. Cela fonctionnera même pour les types complexes.

Questions connexes