2012-02-24 3 views
10

Regardons les choses en asssume, que nous avons un funcion modèle:Est-il possible de transmettre un modèle de fonction en tant qu'argument de modèle?

template<typename T1, typename T2, typename T3> 
T3 such_fun(T1 a, T2 b) { 
    // do something... 
} 

et maintenant nous voulons l'utiliser comme un argument dans un autre modèle, par exemple comme ça

template<typename T1, template<typename, typename, typename> some_function> 
void big_fun(T1 a) { 
    // some code... 
    a = some_function<T1, T1, T1>(a, a); 
    // some code... 
} 

Est-ce possible?

Je sais que je peux utiliser une structure avec un opérateur defined(). Je suis juste curieux de connaître les fonctions.

EDIT:

Pendant que je rédigeais cette question mon ami a trouvé une solution partielle:

template<typename T1, T1 (*some_function)(T1, T1)> 
void big_fun(T1 a) { 
    // some code... 
    a = some_function(a, a); 
    // some code... 
} 

Mais encore - je suis curieux de savoir s'il est possible sans matérialisation d'un type de fonction avant appel. Par exemple - je souhaite appeler le modèle passé avec diverses combinaisons de types:

template<typename T1, typename T2, template<typename, typename, typename> some_function> 
void big_fun(T1 a, T2 b) { 
    // some code... 
    a = some_function<T1, T1, T1>(a, a); 
    a = some_function<T1, T2, T1>(a, b); 
    b = some_function<T2, T2, T2>(b, b); 
    b = some_function<T2, T1, T2>(b, a); 
    // some code... 
} 

Répondre

8

Non, ce n'est pas possible. De 14.3.3 à N3337:

Un modèle argument pour un modèle-paramètre de modèle est le nom d'un modèle de classe ou un modèle d'alias, exprimé en id-expression. Lorsque l'argument de modèle nomme un modèle de classe, seuls les modèles de classe primaire sont pris en compte lors de la mise en correspondance de l'argument modèle modèle avec le paramètre correspondant; Les spécialisations partielles ne sont pas prises en compte même si leurs listes de paramètres correspondent à celle du paramètre de modèle de modèle.

Le premier paragraphe ne mentionne explicitement que les modèles de classe. Je suppose que cela ne vaut pas vraiment la peine étant donné que vous pouvez déjà faire quelque chose de très similaire avec des fonctions ou un std::function comme argument.

+1

Je ne comprends pas un mot de ce que vous dites .. -1, pouvez-vous fournir une illustration pour nous qui ne parlent pas couramment? – lurscher

+0

@lurscher parce que vous ne comprenez pas c'est une horrible raison de downvote. Je ne rejette pas les physiciens quantiques quand ils parlent de la physique quantique parce que je ne la comprends pas. –

+0

@SethCarnegie, je ne suis pas d'accord. Je pense que c'est, en soi, une très bonne raison. d'ailleurs, la réponse est fausse aussi; ce que la question veut faire est complètement possible, même en C++ 03.Je pense qu'il y a un décalage entre ce que le SO demande et ce que pmr répond, d'où la downvote. S'il améliore sa réponse je serai plus qu'heureux de le retirer – lurscher

1

Les modèles en C++ sont compilés lors de la compilation en utilisant les types concrets. Ils doivent être connus. Cela dit, vous pouvez aller un peu plus loin avec votre solution partielle en passant un modèle de fonction dont les arguments peuvent être déduits. Notez que cela ne diffère pas de la fonction de passage explicite avec des types concrets que vous devez simplement taper moins.

template<typename T> 
T square(T a, T b) 
{ 
    return a * b; 
} 

template<typename T, T (*some_function)(T, T)> 
T test(T a) 
{ 
    return square (a, a); 
} 

void main() 
{ 
    int a = test<int, square>(2); 
    float b = test<float, square>(2.2f); 
} 
+0

Je ne vois pas vraiment de différence entre ce code et le code «solution partielle». Le fait est que dans cette approche, il est impossible d'utiliser 'some_function' avec différents types sans ajouter explicitement un nouvel argument template. Et je suis curieux de savoir s'il existe un moyen plus flexible (mais toujours sans utilisation en classe). –

0

Tant que template< typename T1, typename T2, typename T3> someTemplate évalue à une classe réelle sans erreurs que vous pouvez l'utiliser avec autant de combinaisons que vous voulez, à l'intérieur d'autres et modèles.

Avez-vous essayé de le compiler? Montrez-nous quelle erreur obtenez-vous (et échantillon concret)

+0

Je sais que je peux utiliser une classe. J'ai écrit ça dans mon post. La question concerne les fonctions communes. Mais d'après ce que @pmr a écrit - cela semble syntaxiquement impossible. –

+1

La syntaxe que l'OP (et par extension vous utilisez) n'est pas valide. La bonne est 'template class someTemplate'. De plus, rien ici ne concerne l'évaluation. Imaginez-le de cette façon: un argument de modèle de gabarit ne peut être comparé qu'avec le nom d'un gabarit de classe ayant la même liste de paramètres de gabarit (ceci est important pour les arguments de gabarit non typé). Ce nom de modèle est ensuite injecté dans l'autre modèle et peut y être instancié. Le problème est 'template de classe'. Je ne vois pas de raison particulière à cette restriction, mais je ne siège pas au comité et je ne suis pas non plus un avocat spécialisé en langue. – pmr

+0

@pmr Uhm. Bien. La syntaxe que j'ai utilisée dans un exemple était partiellement un pseudo-code, c'est-à-dire que je savais que je ne pouvais pas utiliser un mot-clé 'class', donc je n'en ai pas utilisé. C'était à propos de l'idée. –

Questions connexes