Question

Le code ci-dessous ne compile pas dans Visual C ++ 2005.

class SomeClass {
public: boost::function<void()> func;
        SomeClass(boost::function<void()> &func): func(func) { }
};

void someFunc() {
    std::cout << "someFunc" << std::endl;
}

int main() {
    SomeClass sc(boost::function<void()>(&someFunc));
    sc.func(); // error C2228: left of '.func' must have class/struct/union
    return 0;
}

Si je mets entre parenthèses autour de l'argument du constructeur SomeClass ou construit l'objet boost :: fonction en dehors de la liste des arguments, il compile bien.

    SomeClass sc((boost::function<void()>(&someFunc)));
    // or
    boost::function<void()> f(&someFunc);
    SomeClass sc(f);

Quel est le problème avec le code précédent?

Était-ce utile?

La solution

Il est une déclaration de fonction pour une fonction qui prend une référence à un boost:function <void()> et retourner un SomeClass. Vous pouvez mémoriser la règle suivante, qui se révèle applicable à de nombreux autres cas d'homonymie. Vous trouverez des descriptions de ces cas dans la section 8.2 de la norme C ++.

  

Toute construction qui pourrait être une déclaration sera considérée comme une déclaration

Cela signifie, les éléments suivants seront pris comme une déclaration de paramètre, avec des parenthèses superflues

boost::function<void()>(&someFunc)

Si vous supprimez les parenthèses, cela deviendra clair

boost::function<void()> &someFunc

Et donc, toute déclaration ne plus déclarer un objet, mais une fonction

SomeClass sc(boost::function<void()> &someFunc);

Pour résoudre ce problème, utilisez la distribution notation

SomeClass sc((boost::function<void()>)&someFunc);

Ou mettre des parenthèses autour de l'expression entière, comme vous l'avez fait.

Voici la norme dans toute sa gloire 8.2:

  

L'ambiguïté découlant de la similitude entre une fonction de style fonte et une déclaration mentionnée à 6.8 peut également se produire dans le contexte d'une déclaration. Dans ce contexte, le choix est entre une déclaration de fonction avec un ensemble redondant de parenthèses autour d'un nom de paramètre et une déclaration d'objet avec une fonction de style cast comme initialiseur. Tout comme pour les ambiguïtés mentionnées à 6.8, la résolution est de considérer toute construction qui pourrait être une déclaration une déclaration. [Note: une déclaration peut être explicitement désambiguïsé par un casting de style non-fonctionnement, par un = pour indiquer l'initialisation ou en supprimant les parenthèses redondantes autour du nom du paramètre. ]

Notez que pour contrôler la priorité, vous êtes autorisé à introduire entre parenthèses à peu près partout, comme dans les domaines suivants

int (((((((a))))))) = 3;
int (*(pa)) = &a;

Autres conseils

Ceci est connu comme "le plus contrariant Parse de C ++" (de une livre de Scott Meyers a appelé efficace STL).

réponse ci-dessus , le compilateur préfère interpréter la ligne problématique comme une déclaration de fonction.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top