Opérateur ternaire + constructeur C++11 à partir de la liste d'initialiseur

en développant une application, j'ai eu le problème suivant. Je voulais revenir un vide std::list<string> quand un pointeur de fonction est nulle, ou le résultat de cette fonction autrement. C'est une version simplifiée de mon code:

typedef std::list<std::string> (*ParamGenerator)();

std::list<std::string> foo() {
    /* ... */
    ParamGenerator generator = ...;
    if(generator)
        return generator();
    else
        return {};
}

cependant, j'aime généralement utiliser le ternaire (?:) opérateur dans ces cas, j'ai donc essayé de l'utiliser de cette façon (comme d'habitude):

return generator ? generator() : {};

Mais j'ai reçu ce message d'erreur:

somefile.cpp:143:46: error: expected primary-expression before ‘{’ token
somefile.cpp:143:46: error: expected ‘;’ before ‘{’ token

est-ce que cela signifie que je ne peux pas utiliser le ternaire opérateur pour retourner les objets créés en utilisant leur constructeur à partir d'un <!--5? Est-il une raison particulière à cela?

22
demandé sur Ryan Haining 2012-04-02 23:35:57

3 réponses

Standard écrit en 8.5.4.1: List-initialization

Note: la Liste d'initialisation peut être utilisé

  • comme initialiseur dans une définition variable (8.5)
  • comme l'initialiseur dans une nouvelle expression (5.3.4)
  • dans une instruction de retour (6.6.3)
  • comme argument de fonction (5.2.2)
  • comme indice (5.2.1)
  • comme argument à l'invocation d'un constructeur (8.5, 5.2.3)
  • comme initialiseur pour un membre de données non statique (9.2)
  • dans un mem-initialiseur (12.6.2)
  • sur le côté droit d'une affectation (5.17)

Rien d'eux est un opérateur ternaire. Le plus minimaliste return 1?{}:{}; est invalide aussi, ce que vous voulez est impossible.

bien sûr, vous pouvez appeler explicitement le constructeur std::list<std::string>{}, mais je vous recommande d'écrire l' if-elsebloc que vous c'est déjà fait.

15
répondu ipc 2012-04-02 19:56:24

Lorsque vous faites {} le compilateur n'a aucune connaissance du type que vous attendez, donc c'est juste une expression dénuée de sens que le compilateur ne sait pas quoi faire avec. Des deux côtés de l' : sont évalués séparément, et alors seulement, le compilateur se plaindre si les types ne correspondent pas. Je voudrais juste faire ceci:

return generator ? generator() : std::list<std::string>();
5
répondu spencercw 2012-04-02 19:48:06

Si vous aimez vraiment l'opérateur ternaire, vous pouvez essayer quelque chose comme ceci:

return generator ? generator() : decltype(generator()) { "default value", "generator was empry" };

cela fonctionnera même si vous changez les types de retour plus tard.

2
répondu Ivan 2012-04-02 20:36:33