Visual Studio 2010 et std :: fonction
-
19-09-2019 - |
Question
J'ai ce code:
#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. J'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. Il ne fonctionne pas seulement avec le nouveau Visual Studio 2010 Beta 2 Les cartes Express et Release Candidate.
Est-ce nouveau fonctionnalités C ++ buggé dans VS2010? Ou il y a une erreur ou une mauvaise utilisation dans le code?
La solution
Je pense que je l'ai 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 retour de reference_wrapper<T>::operator()
:
La mise en œuvre peut déterminer l'élément de 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 le paragraphe 3:
Si F est pas un objet de fonction définie par la bibliothèque standard, et si soit la mise en oeuvre ne peut pas déterminer le type de l'expression f (t1, t2, ..., tN) ou si l'expression est mal formé, le la mise en œuvre doit utiliser le processus suivant pour déterminer le membre du type:
- Si F est un type de classe peut-cv-qualifié sans membre nommé
result_type
ou sitypename F::result_type
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 il devrait fonctionner, je pense. Notez que dans C++0x
, ce qui est différent. Elle ne repose pas sur result_type
ou un modèle de result
, car il peut utiliser decltype
.
Si avec <functional>
il échoue avec MSVC10 en mode C ++ 0x, il sent comme un bug, je dirais. Mais peut-être quelqu'un d'autre sait ce qui se passe. Il peut (mais non garanti) travailler avec <tr1/functional>
en mode C ++ 0x si cet en-tête choisit de prendre le chemin de decltype
au lieu de ::result_type
. Je typedef result_type
- cette façon, je pense qu'il devrait toujours fonctionner indépendamment du fait que l'en-tête de tr1
est utilisé ou l'en-tête de 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&
).
Autres conseils
Je rencontre un problème similaire ici: empêcher les copies inutiles de la foncteur de C des objets
Pour le compiler sur MSVC10, je devais tirer mon objet fonction de std :: unary_function.