En parcourant l'implémentation actuelle de gcc des nouveaux en-têtes C ++ 11, je suis tombé sur le jeton "......". Vous pouvez vérifier que le code suivant se compile correctement [via ideone.com].
template <typename T>
struct X
{ /* ... */ };
template <typename T, typename ... U>
struct X<T(U......)> // this line is the important one
{ /* ... */ };
Alors, quelle est la signification de ce jeton?
edit: On dirait que SO coupé "......" dans le titre de la question à "...", je voulais vraiment dire "......". :)
c++
c++11
variadic-templates
Vitus
la source
la source
...
suivi de...
.U...
suivi par...
. Très étrange néanmoins.<functional>
et<type_traits>
, toujours dans le contexte d'une liste d'arguments de fonction à l'intérieur d'un paramètre de modèle.Réponses:
Chaque instance de cette bizarrerie est associée au cas d'une seule ellipse régulière.
Je suppose que la double ellipse a un sens similaire à
_ArgTypes..., ...
, c'est- à -dire une expansion de modèle variadique suivie d'une liste de varargs de style C.Voici un test qui soutient cette théorie… Je pense que nous avons un nouveau gagnant pour le pire pseudo-opérateur de tous les temps.
Edit: Cela semble être conforme. Le §8.3.5 / 3 décrit une manière de former la liste de paramètres comme
Ainsi, la double ellipse est formée par une liste de déclaration de paramètres se terminant par un pack de paramètres, suivie d'une autre ellipse.
La virgule est purement facultative; §8.3.5 / 4 dit
C'est dans un abstrait déclarateur, [modifier] mais Johannes fait un bon point qu'ils font référence à un résumé-déclarateur dans un paramètre-déclaration. Je me demande pourquoi ils n'ont pas dit "une partie d'une déclaration de paramètre" et pourquoi cette phrase n'est pas qu'une note informative ...
De plus,
va_begin()
in<cstdarg>
requiert un paramètre avant la liste varargs, donc le prototypef(...)
spécifiquement autorisé par C ++ est inutile. Les renvois avec C99, c'est illégal en plein C. Donc, c'est très bizarre.Note d'utilisation
Sur demande, voici une démonstration de la double ellipse:
la source
std::is_function
'svalue
doit être vrai même si la fonction est C varargs one et parce que T (U ...) ne correspond pas à une telle fonction, vous avez besoin de cette folie. Par exemple, int f (int, char, ...) correspond exactement à T (U ......) avec T = int, U = {int, char} et le jeton varargs "...".void (int...)
ici, le...
ne fait pas partie du déclarateur abstraitint
, il est donc synonyme devoid(int, ...)
. Si vous écrivezvoid(T...)
etT
est un pack de paramètres de modèle,...
ferait partie du déclarateur abstrait, et par conséquent, il ne serait pas équivalent àvoid(T, ...)
.f(...)
est largement utilisé comme surcharge de fonction de secours dans la métaprogrammation de modèle, où ces informations ne sont pas nécessaires (et où la fonction n'est même pas réellement appelée).sur vs2015, séparer la virgule est essentiel dans la version du modèle:
un exemple d'instanciation est:
salutations, FM.
la source