2009-06-14 8 views
2

Le code ci-dessous ne compile pas dans Visual C++ 2005.Erreur C2228 lors de la construction boost :: objet fonction dans la liste des arguments constructeur

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'élan: : objet de fonction en dehors de la liste d'arguments qu'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?

Répondre

1

Il s'agit d'une déclaration de fonction pour une fonction prenant la référence boost:function <void()> et renvoyant un SomeClass. Vous pouvez mémoriser la règle suivante, qui s'avère s'appliquer à beaucoup d'autres cas de désambiguïsation de ce type. Vous pouvez trouver des descriptions de ces cas dans la section 8.2 de la norme C++.

Toute construction qui pourrait être une déclaration sera prise comme une déclaration

Cela signifie que, 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 

Ainsi, 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 le cast notation

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

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

est la norme dans toute sa gloire de 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 un cast de style fonction comme initialiseur. Tout comme pour les ambiguïtés mentionnées en 6.8, la résolution consiste à considérer toute construction qui pourrait éventuellement être une déclaration comme une déclaration. [Note: une déclaration peut être explicitement désambiguïsée par un cast non fonctionnel, par a = 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 le

int (((((((a))))))) = 3; 
int (*(pa)) = &a; 
suivant
Questions connexes