Przeglądając aktualną implementację nowych nagłówków C ++ 11 w gcc, natknąłem się na token „......”. Możesz sprawdzić, czy poniższy kod kompiluje się dobrze [przez ideone.com].
template <typename T>
struct X
{ /* ... */ };
template <typename T, typename ... U>
struct X<T(U......)> // this line is the important one
{ /* ... */ };
Więc jakie jest znaczenie tego tokena?
edycja: Wygląda na tak przycięty „......” w tytule pytania do „…”, naprawdę miałem na myśli „......”. :)
c++
c++11
variadic-templates
Vitus
źródło
źródło
...
następuje po nim...
.U...
następuje...
. Niemniej jednak bardzo dziwne.<functional>
i<type_traits>
, zawsze w kontekście listy argumentów funkcji wewnątrz parametru szablonu.Odpowiedzi:
Każde wystąpienie tej osobliwości jest powiązane z przypadkiem zwykłej pojedynczej wielokropka.
Domyślam się, że podwójny wielokropek ma podobne znaczenie
_ArgTypes..., ...
, np. Wariadyczne rozwinięcie szablonu, po którym następuje lista varargs w stylu C.Oto test potwierdzający tę teorię… Myślę, że mamy nowego zwycięzcę dla najgorszego pseudo-operatora wszechczasów.
Edycja: wydaje się, że jest to zgodne. W §8.3.5 / 3 opisano jeden ze sposobów tworzenia listy parametrów jako
Tak więc podwójny wielokropek jest tworzony przez listę deklaracji parametrów kończącą się pakietem parametrów, po której następuje kolejny wielokropek.
Przecinek jest całkowicie opcjonalny; §8.3.5 / 4 mówi
Dzieje się to w ramach abstrakcyjnego-deklaratora, [edytuj], ale Johannes dobrze zauważa, że odnoszą się one do abstrakcyjnego-deklaratora w deklaracji parametru. Zastanawiam się, dlaczego nie powiedzieli „część deklaracji parametru” i dlaczego to zdanie nie jest tylko informacją…
Ponadto
va_begin()
in<cstdarg>
wymaga parametru przed listą varargs, więc prototypf(...)
wyraźnie dozwolony przez C ++ jest bezużyteczny. Powiązanie z C99 jest nielegalne w zwykłym C. To jest najbardziej dziwne.Uwaga dotycząca użytkowania
Na życzenie przedstawiam podwójną wielokropek:
źródło
std::is_function
svalue
musi być prawdziwe, nawet jeśli funkcja jest jedną z C varargs i ponieważ T (U ...) nie pasuje do takiej funkcji, potrzebujesz tego szaleństwa. Np. Int f (int, char, ...) dopasowuje T (U ......) dokładnie z T = int, U = {int, char} i tokenem varargs „...”.void (int...)
Tutaj,...
nie jest częścią abstrakcyjnego-deklaratoraint
, stąd jest synonimemvoid(int, ...)
. Jeśli napisałbyśvoid(T...)
iT
jest pakietem parametrów szablonu,...
byłby częścią abstrakcyjnego deklaratora, a zatem nie byłby równoważny zvoid(T, ...)
.f(...)
jest często używany jako przeciążenie funkcji rezerwowej w metaprogramowaniu szablonów, gdzie ta informacja nie jest konieczna (a funkcja nawet nie jest wywoływana).w vs2015 przecinek oddzielający jest niezbędny w wersji szablonu:
przykładowa instancja to:
pozdrawiam, FM.
źródło