Etude du C++ Technical Report 1 - reference_wrapper : je confirme, c'est tordu. | 2 vote(s)
Par Emmanuel Deloget, lundi 1 septembre 2008 à 14:00 :: C++ :: permalien #138
Tags: C++, héritage, meta-programmation, standard, TR1
Souvenez vous : il y a près de deux ans, j'essayais avec grand peine d'implémenter la classe std::tr1::reference_wrapper<>, et j'ai du abandonner.Tout content de pouvoir installer l'implémentation du TR1 de Microsoft Visual C++ 2008 SP1, j'ai tenu à vérifier que mon échec épique n'était pas du à ma stupidité, mais à (comme je le pense sincèrement) une mauvaise formulation du texte du TR1.
Le problème se situe dans le document ISO/IEC DT 19768 (pdf), section 2.1.2, paragraphes 2, 3, 4.
2. reference_wrapper has a weak result type (3.3).
3. The template instantiationreference_wrapper<T>shall be derived fromstd::unary_function<T1, R>only if the type T is any of the following:
-- a function type or a pointer to function type taking one argument of type T1 and returning R
-- a pointer to member function type with cv-qualifier cv and no arguments; the type T1 is cv T* and R is the return type of the pointer to member function
-- a class type that is derived fromstd::unary_function<T1, R>
4. The template instantiationreference_wrapper<T>shall be derived fromstd::binary_function<T1, T2, R>only if the type T is any of the following:
-- a function type or a pointer to function type taking two arguments of types T1 and T2 and returning R
-- a pointer to member function with cv-qualifier cv and taking one argument of type T2; the type T1 is cv T* and R is the return type of the pointer to member function
-- a class type that is derived fromstd::binary_function<T1, T2, R>
Des paragraphes 3 et 4, il découle que si la class C1 dérive à la fois de std::unary_function<> et std::binary_function<>, alors reference_wrapper<C1> doit dériver de ces deux types.
Le paragraphe 2 nous renvoie à la section 3.3, paragraphe 3.
3. If a call wrapper (3.1) has a weak result type the type of its member type
result_typeis based on the type T of the wrapper’s target object (3.1):
-- if T is a function, reference to function, or pointer to function type,result_typeshall be a synonym for the return type of T;
-- if T is a pointer to member function,result_typeshall be a synonym for the return type of T;
-- if T is a class type with a member typeresult_type, thenresult_typeshall be a synonym forT::result_type;
-- otherwise result_type shall not be defined.
Puisque std::unary_function<> et std::binary_function<> définissent tous les deux le type result_type, C1 hérite de ces types. Dans ce contexte, faire référence à C1::result_type provoque une erreur du à l'ambiguïté. Dans ce contexte, il est normalement impossible de définir reference_wrapper<C1>::result_type.
Je suis rassuré par le fait suivant: l'implémentation du TR1 fournie par Microsoft dans Visual C++ 2008 SP1 butte sur ce problème. L'implémentation présente dans GCC élimine le problème en considérant que C1 ne définit pas de type result_type (ce qui n'est pas illogique, mais la technique de découverte de cette information n'est pas portable de GCC à Visual C++ -- et le compilateur Comeau se comporte encore de manière différente vis-à-vis de ce problème).
Mon échec n'était donc pas si épique. Ou alors, il l'est encore plus que ce que j'imaginais (à savoir que le cas cité n'est même pas censé se présenter dans votre code si vous êtes un tant soit peu respectueux des autres personnes qui travaillent avec vous...).
Commentaires
Aucun commentaire pour le moment.
:: Fil rss des commentaires de ce billet ::
Ajouter un commentaire