11

J'ai ce code:Visual Studio 2010 et std :: fonction

#include <iostream> 
#include <functional> 

struct A 
{ 
    int operator()(int i) const { 
     std::cout << "F: " << i << std::endl; 
     return i + 1; 
    } 
}; 

int main() 
{ 
    A a; 
    std::tr1::function<int(int)> f = std::tr1::ref(a); 
    std::cout << f(6) << std::endl; 
} 

Le but est de passer l'objet foncteur par un reference_wrapper, de manière à éviter les appels inutiles copie de costructor. je me attends à la sortie suivante:

F: 6 
7 

Il fonctionne correctement avec GCC> = 4.4.0, Visual Studio 2008 et coup de pouce en remplaçant std :: espace de noms TR1 avec boost. Cela ne fonctionne pas avec le nouveau Visual Studio 2010 à la fois Express Beta 2 et Release Candidate.

Ces nouvelles fonctionnalités C++ sont-elles buggées dans vs2010? Ou il y a une erreur ou une mauvaise utilisation dans le code?

+0

Comment ça ne marche pas? – UncleBens

+0

@litb: Je pense que l'OP a des problèmes avec l'utilisation de la classe de template 'std :: tr1 :: ref' et * not * boost sur VS2010. – dirkgently

+0

est ici la sortie de génération de VS2010: http://pastebin.com/YQf4Qe8W –

Répondre

11

Je pense avoir trouvé la raison. C'est ce que TR1 3.4/2 dit à propos result_of<T(A1, A2, ..., AN)>::type, utilisé dans la détermination du type de reference_wrapper<T>::operator() de retour:

La mise en œuvre peut déterminer le membre du type par tout moyen qui produit le type exact de l'expression f (t1, t2, ..., tN) pour les types donnés. [Note: L'intention est que les implémentations sont autorisés à utiliser la note spéciale crochets du compilateur]

Et puis le paragraphe 3:

Si F n'est pas un objet de fonction définie par la bibliothèque standard, et si l'implémentation ne peut pas déterminer le type de l'expression f (t1, t2, ..., tN) ou si l'expression est mal formée, l'implémentation doit utiliser le processus suivant pour déterminer le membre de type:

  • Si F est un type de classe possiblement qualifié cv sans memb er nommé result_type ou si typename F::result_type n'est pas un type:
    • Si N = 0 (aucun argument), le type est vide.
    • Si N> 0, le type est typename F::template result<F(T1, T2,..., TN)>::type

Le message d'erreur est un artefact d'essayer ces automne-backs. Fournir un typedef pour result_type à int et cela devrait fonctionner, je pense. Notez que dans C++0x, c'est différent. Il ne repose pas sur result_type ou un modèle result, car il peut utiliser decltype.

Si avec <functional> il échoue avec MSVC10 en mode C++ 0x, ça sent comme un bug, dirais-je. Mais peut-être que quelqu'un d'autre sait ce qui se passe. Il peut (mais n'est pas garanti de) travailler avec <tr1/functional> en mode C++ 0x si cet en-tête choisit de prendre la voie decltype au lieu de ::result_type. Je voudrais typedef result_type - de cette façon, je pense que cela devrait toujours fonctionner, peu importe si l'en-tête tr1 est utilisé ou l'en-tête c++0x.


Notez également que boost::tr1 dit dans sa documentation qu'il ne supporte pas l'opérateur d'appel de fonction (mais il supporte uniquement les conversions implicites à T&).

+1

Oui, cela résoudre le problème: D C'est un dommage pour vs2010 pour cette régression par rapport à la version précédente de 2008 ... Le projet le plus récent exige strictement que le compilateur reconnaisse automatiquement le type de retour http://www.open-std.org/JTC1/SC22/ WG21/docs/papers/2009/n3000.pdf Paragraphe 20.7.4 –