2010-02-16 6 views
7

Observation: the codes pasted below were tested only with GCC 4.4.1, and I'm only interested in them working with GCC.objet construction/avant d'ambiguïté de la déclaration de fonction

Bonjour,

Il n'y avait pas seulement quelques fois que je suis tombé dans une déclaration de construction de l'objet que je ne comprenais pas, et il était seulement aujourd'hui que j'ai remarqué quelle ambiguïté était introduite par elle. Je vais vous expliquer comment le reproduire et j'aimerais savoir s'il y a moyen de le réparer (C++ 0x autorisé). Ici ça va. Supposons qu'il existe une classe dont le constructeur prend un seul argument, et que le type de cet argument est une autre classe avec un constructeur par défaut. Par exemple:

struct ArgType {}; 

class Class 
{ 
public: 
    Class(ArgType arg); 
}; 

Si je tente de construire un objet de type Class sur la pile, je reçois une ambiguïté:

Class c(ArgType()); // is this an object construction or a forward declaration 
        // of a function "c" returning `Class` and taking a pointer 
        // to a function returning `ArgType` and taking no arguments 
        // as argument? (oh yeh, loli haets awkward syntax in teh 
        // saucecode) 

Je dis que c'est une construction de l'objet, mais le compilateur insiste qu'il est une déclaration avant à l'intérieur du corps de la fonction. Pour vous qui ne l'obtenez toujours pas, voici un exemple de travail complet:

#include <iostream> 

struct ArgType {}; 
struct Class {}; 

ArgType func() 
{ 
    std::cout << "func()\n"; 
    return ArgType(); 
} 

int main() 
{ 
    Class c(ArgType()); 

    c(func); // prints "func()\n" 
} 

Class c(ArgType funcPtr()) // Class c(ArgType (*funcPtr)()) also works 
{ 
    funcPtr(); 
    return Class(); 
} 

Alors, assez d'exemples. Tout le monde peut m'aider à contourner cela sans rien faire de trop anti-idiomatique (je suis un développeur de bibliothèques, et les gens aiment les bibliothèques idiomatiques)?

- éditer

Peu importe. C'est une dupe de Most vexing parse: why doesn't A a(()); work?.

Merci, sbi.

+0

Votre code me compile pour avec g ++ - quel bit pensez-vous ne devrait pas travailler? –

+0

Il ne s'agit pas de travailler ou de ne pas travailler. Le problème est que je voulais juste construire un objet de type 'Class' et passer à son constructeur un objet de type' ArgType' construit en ligne .. Mais il reconnaît comme une déclaration forward. Je vais ajouter du code que je voulais travailler mais je ne peux pas, juste une seconde. –

+0

Oublie ça, Neil. Regardez la réponse de sbi, c'est exactement mon problème. –

Répondre

5

Ceci est connu comme "l'analyse la plus vexante de C++". Voir here, here et here.

1

Basé sur le « C++ 0x autorisé », la bonne réponse est (probablement) de modifier la définition à:

Class c(ArgType {}); 

simple, direct et met le fardeau entièrement sur l'utilisateur de la bibliothèque, pas l'auteur!

Editer: Oui, le ctor est invoqué - C++ 0x ajoute List-Initialization comme moyen non ambigu de délimiter les listes d'initialisation. Il ne peut pas être mal analysé comme dans votre échantillon, mais sinon le sens est à peu près le même que si vous avez utilisé des parenthèses. Voir N3000, le troisième point sous §8.5.4/3. Vous pouvez écrire un ctor pour recevoir une liste d'initialisation en tant qu'argument unique, ou les éléments de la liste d'initialisation peuvent être associés individuellement aux arguments ctor.

+0

Attendez .. mais cela n'appellerait pas le constructeur, n'est-ce pas? –

+1

En fait, cela ne semble pas acceptable à GCC 4.4.1. D'autres combinaisons sont cependant: 'Class c {ArgType {}};' ou 'Class c {ArgType()};' Et ajoutant une version non-C++ 0x d'invoquer le constructeur: 'Class c ((ArgType())); ' – UncleBens

1

Simplifions-nous un peu.

int f1(); 

Qu'est-ce que c'est? Le compilateur (et moi) dit que c'est une déclaration en avant pour une fonction renvoyant un entier.

Que pensez-vous de cela?

int f2(double); 

Le compilateur (et I) indique qu'il s'agit d'une déclaration directe pour une fonction prenant un double argument et retournant un int.

Alors avez-vous essayé ceci:

ClassType c = ClassType(ArgType()); 

Vérifiez le C++ Faq lite sur constructors pour explanations et des exemples

Questions connexes