web-dev-qa-db-fra.com

Les packs de paramètres non développés avec '...'

J'ai ce 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;
}

Cela génère une erreur:

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

Pourquoi l'utilisation de la fonction pass() est-elle nécessaire?

12
q126y

Essentiellement, le développement d'un paquet de paramètres E... produit un list E1, E2, [...], EN, une E pour chaque élément du paquet. Cette construction syntaxique n'est valide que dans les endroits où les listes sont grammaticalement correctes, telles que les appels de fonction, les listes d'initialiseur, etc. Une expression contenant plusieurs opérateurs de virgule ne compte pas.

Je pense qu'avec expressions de pliage _ ( N4295: expressions de pliage (Andrew Sutton, Richard Smith) } _), vous pourrez simplement écrire:

(print(a), ...);

Dans cette expression, 

  • print(a) est une expression avec un pack de paramètres non expansé,
  • , est l'opérateur et 
  • ... désigne la bonne extension du pli. 

Le résultat de l'expression entière est que (print(a), ...) sera transformé en 

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

Les extensions de packs ne peuvent se produire que dans des contextes d'extension de packs. Ce sont essentiellement:

  • initialisation renforcée
  • listes d'initialisation
  • initialisations globales
  • appels de fonction
  • initialisations de tableau

Le plus facile à utiliser dans votre cas serait le dernier:

#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
Nikos Athanasiou

Celui-ci fonctionne aussi:

#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