web-dev-qa-db-de.com

Parameterpakete nicht mit '...' erweitert

Ich habe diesen Code:

#include <iostream>
using namespace std;

int print(int i)
{
    cout << endl << i;
}

template<typename ...Args>
inline void pass(Args&&...args)
{

}

template<typename ...args>
inline void expand(args&&... a)
{
    print(a) ...; //this doesn't expand
    //pass( print(a)... ); this works
}

int main() {
    expand(1,2,3,4);
    return 0;
}

Es wirft einen Fehler:

 In function 'void expand(args&& ...)':
error: expected ';' before '...' token
  print(a) ...;
           ^
parameter packs not expanded with '...':
  print(a) ...;
              ^

Warum ist die Verwendung der Funktion pass() notwendig?

12
q126y

Das Erweitern eines Parameterpakets E... erzeugt im Wesentlichen eine list E1, E2, [...], EN, eine E für jedes Element im Paket. Dieses syntaktische Konstrukt ist nur an Stellen gültig, an denen Listen grammatikalisch korrekt sind, z. B. in Funktionsaufrufen, Initialisierungslisten usw. Ein Ausdruck, der mehrere Kommaoperatoren enthält, zählt nicht.

Ich glaube, dass Sie mit fold-Ausdrücken ( N4295: Folding-Ausdrücke (Andrew Sutton, Richard Smith) ) einfach schreiben können:

(print(a), ...);

In diesem Ausdruck 

  • print(a) ist ein Ausdruck mit einem nicht erweiterten Parameterpaket.
  • , ist der Operator und 
  • ... bezeichnet die Erweiterung der rechten Falte. 

Das Ergebnis des gesamten Ausdrucks ist, dass (print(a), ...) in umgewandelt wird 

print(a1) , (print(a2), (print(a3), print(a4))) // (assuming four elements). 
16
TartanLlama

Pack-Erweiterungen können nur in Pack-Erweiterungskontexten erfolgen. Dies sind im Wesentlichen:

  • geschweifte Initialisierung
  • initialisierungslisten
  • aggregierte Initialisierungen
  • funktionsaufrufe
  • array-Initialisierungen

Von diesen wäre die einfachere Verwendung in Ihrem Fall die letzte:

#include <iostream>
using namespace std;
int print(int i)
{
    cout<<endl<<i;
    return 0;
}

template<typename ...args>
inline void expand(args&&... a)
{
    using expander = int[]; 
    (void)expander{0, ((void)print(a), 0)...}; 
}

int main() 
{
    expand(1,2,3,4);

    return 0;
}

Demo

6

Dieser funktioniert auch:

#include <iostream>

void print() {}

template<typename T, typename ... Types>
void print (T firstArg, Types ... args) {
    std::cout << firstArg << "\n";
    print(args...);
}

int main() {
    print("Hello",1337,42.44,"World");
}

Demo

0
cosurgi