Arguments par défaut du modèle

151

Si je suis autorisé à faire ce qui suit:

template <typename T = int>
class Foo{
};

Pourquoi ne suis-je pas autorisé à faire ce qui suit en général?

Foo me;

Mais je dois préciser ce qui suit:

Foo<int> me;

C ++ 11 a introduit des arguments de modèle par défaut et pour le moment, ils sont insaisissables pour ma compréhension complète.

user633658
la source

Réponses:

188

Tu dois faire:

Foo<> me;

Les arguments du modèle doivent être présents mais vous pouvez les laisser vides.

Pensez-y comme une fonction fooavec un seul argument par défaut. L'expression foone l'appellera pas, mais le foo()fera. La syntaxe de l'argument doit toujours être là. Ceci est cohérent avec cela.

Joseph Mansfield
la source
4
@Pubby Je suppose que cela créerait des complications inutiles si Foo peut - être un identificateur de modèle ou peut - être une instanciation explicite selon que il y a un argument par défaut. Mieux vaut conserver la syntaxe d'instanciation explicite. Pensez-y comme une fonction fooavec un seul paramètre par défaut. Vous ne pouvez pas l'appeler comme foo, vous l'appelez avec foo(). Il est logique de garder cela cohérent.
Joseph Mansfield
2
@sftrabbit mais vous ne pouvez pas appeler une fonction sans arguments comme l'un fooou l'autre; vous pouvez cependant nommer une classe sans argument Foo.
Seth Carnegie
4
@aschepler Avec une fonction, les arguments du modèle peuvent être déduits des arguments de la fonction. Avec une classe, il n'est pas possible de décider si vous voulez dire une classe modèle avec des arguments par défaut ou une classe non modèle.
Olaf Dietsche
21
@OlafDietsche mais vous ne pouvez pas avoir de classe modèle et une classe non modèle avec le même nom, donc le compilateur devrait être en mesure de décider en regardant simplement quel est le nom.
Seth Carnegie
7
@Pubby Le comité standard s'est posé la même question, je suppose. Désormais, avec C ++ 17, le <>n'est plus nécessaire dans ce cas. Consultez ma réponse pour plus de détails.
Paolo M
53

Avec C ++ 17, vous pouvez en effet.

Cette fonctionnalité est appelée déduction d'argument de modèle de classe et ajoute plus de flexibilité à la façon dont vous pouvez déclarer des variables de types modèles .

Alors,

template <typename T = int>
class Foo{};

int main() {
    Foo f;
}

est maintenant du code C ++ légal .

Paolo M
la source
5
Étrange. Je l'ai juste essayé dans mon projet C ++ 17 et cela n'a pas fonctionné: "le type d'espace réservé de modèle 'const MyType' doit être suivi d'un simple déclarator-id". J'utilise GCC 7.3.0.
Silicomancer
1
@Silicomancer C'est difficile à dire sans voir votre code et votre ligne de commande ... Peut-être avez-vous affaire à des pointeurs comme ici ?
Paolo M
1
Clang n'accepte pas, semble-t-il? coliru.stacked-crooked.com/a/c5d3c0f90ed263c2
Borgleader
1
@Borgleader Apparemment, Coliru utilise clang 5.0. À en juger par cela , il devrait prendre en charge la déduction d'arguments de modèle C ++ 17, mais évidemment pas id. Si vous essayez votre même exemple dans wandbox en utilisant clang 7.0, cela fonctionne parfaitement.
Paolo M
2
@PaoloM Oh cool, heureux de savoir que c'est juste un problème de version de compilateur. Merci d'avoir examiné cela.
Borgleader
19

Vous n'êtes pas autorisé à faire cela mais vous pouvez le faire

typedef Foo<> Fooo;

puis fais

Fooo me;
g24l
la source
y a-t-il une différence avec un type par défaut et:, typedef Foo<float> Fooo;sans un type par défaut?
qrikko
5
La manière C ++ 11-ish serait de direusing Fooo = Foo<>;
Adrian W
18

Vous pouvez utiliser les éléments suivants:

Foo<> me;

Et intsoyez votre argument modèle. Les crochets angulaires sont nécessaires et ne peuvent pas être omis.

Andy Prowl
la source
Cela a du sens et merci, mais, comme indiqué ci-dessous, pourquoi le type spécifié ne doit-il pas être présent?
user633658
@ user633658: Voulez-vous dire "spécificateur de type"? Je ne suis pas sûr de comprendre
Andy Prowl
Quoi qu'il en soit, en ce qui concerne la raison de la nécessité de crochets angulaires vides, je ne peux que faire des conjectures, et il s'agit d'écarter les ambiguïtés possibles avec l'utilisation du nom du modèle seul, mais je dois avouer que je ne connais pas l'exact raison
Andy Prowl
Je soupçonne fortement que l'exigence de <> est d'activer l'analyseur du compilateur pour déterminer que vous faites référence à une classe basée sur un modèle appelée foo, plutôt qu'à quelque chose d'autre appelé foo.
Mac