Jakie jest znaczenie "... ... " tokena? tj. operator podwójnej elipsy na pakiecie parametrów

Przeglądając aktualną implementację GCC nowych nagłówków C++11, natknąłem się na "......"token. Możesz sprawdzić, czy poniższy kod kompiluje fine [poprzez 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 żetonu?

Edit: wygląda tak przycięte "......"w pytaniu tytuł do"...", Naprawdę miałem na myśli "......" . :)

Author: Patrick Fromberg, 2011-04-11

2 answers

Każdy przypadek tej dziwności jest sparowany z przypadkiem regularnej pojedynczej elipsy.

  template<typename _Res, typename... _ArgTypes>
    struct _Weak_result_type_impl<_Res(_ArgTypes...)>
    { typedef _Res result_type; };

  template<typename _Res, typename... _ArgTypes>
    struct _Weak_result_type_impl<_Res(_ArgTypes......)>
    { typedef _Res result_type; };

  template<typename _Res, typename... _ArgTypes>
    struct _Weak_result_type_impl<_Res(_ArgTypes...) const>
    { typedef _Res result_type; };

  template<typename _Res, typename... _ArgTypes>
    struct _Weak_result_type_impl<_Res(_ArgTypes......) const>
    { typedef _Res result_type; };

Domyślam się, że Podwójna elipsa jest podobna w znaczeniu do _ArgTypes..., ..., tzn. zmiennego rozszerzenia szablonu, po którym następuje lista varargs w stylu C.

Oto test potwierdzający tę teorię ... myślę, że mamy nowego Zwycięzcę najgorszego pseudo-operatora.

Edit: to wydaje się być zgodne. §8.3.5 / 3 opisuje jeden sposób tworzenia listy parametrów as

Parameter-declaration-listopt ... opt

Tak więc Podwójna elipsa jest tworzona przez parametr-deklarację-listę kończącą się pakietem parametrów, po którym następuje kolejna elipsa.

Przecinek jest czysto opcjonalny; §8.3.5/4 mówi

Gdzie poprawne składniowo i gdzie "..."nie jest częścią abstract-declarator,",..."jest synonimem "...".

To jest w obrębie abstract-declarator, [edytuj] ale Johannes zwraca uwagę, że odwołują się do deklaratora abstrakcyjnego w parametrze-deklaracji. Zastanawiam się, dlaczego nie powiedzieli "część parametru-deklaracji" i dlaczego to zdanie nie jest tylko notatką informacyjną ...

Ponadto, va_begin() w <cstdarg> wymaga parametru przed listą varargs, więc prototyp f(...) specjalnie dozwolony przez C++ jest bezużyteczny. Porównywanie z C99, jest nielegalne w prostym C. Więc jest to najbardziej dziwne.

Uwaga dotycząca użytkowania

Na życzenie, oto demonstracja podwójnej elipsy:

#include <cstdio>
#include <string>

template< typename T >
T const &printf_helper( T const &x )
    { return x; }

char const *printf_helper( std::string const &x )
    { return x.c_str(); }

template< typename ... Req, typename ... Given >
int wrap_printf( int (*fn)( Req... ... ), Given ... args ) {
    return fn( printf_helper( args ) ... );
}

int main() {
    wrap_printf( &std::printf, "Hello %s\n", std::string( "world!" ) );
    wrap_printf( &std::fprintf, stderr, std::string( "Error %d" ), 5 );
}
 77
Author: Potatoswatter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-12 12:49:40

Na vs2015 separacja przecinków jest niezbędna w wersji szablonu:

    template <typename T, typename ... U>
    struct X<T(U...,...)> {};// this line is the important one

Przykładowa instancja to:

    X<int(int...)> my_va_func;

Pozdrawiam, FM.

 2
Author: Red.Wave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-26 17:40:50