ne fournit pas d'erreur d'opérateur d'appel" lors de la tentative de validation de la fonction de retour de la fonction - Retrouvez les réponses et les commentaires concernant cette question" />
9
votes

" ne fournit pas d'erreur d'opérateur d'appel" lors de la tentative de validation de la fonction de retour de la fonction

J'essaie d'écrire une fonction qui prendra un agenceur comme argument, appelez le fonctionnaire, puis renvoyé sa valeur de retour enveloppée dans un boost :: Shared_ptr code>.

Les éléments suivants refusent Compiler et je suis tout à fait des idées. Je reçois "std :: vecteur ne fournit pas d'opérateur d'appel" (grossièrement). J'utilise Clang 3.1 sur Mac OS X. P>

#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

#include <string>
#include <vector>

std::vector< std::string > foo()
{
  std::vector< std::string > vec;
  return vec;
}

template< typename T >
boost::shared_ptr< T > ReturnValueAsShared(
    boost::function< T() > func )
{
  return boost::make_shared< T >( func() );
}

int main()
{
  auto f = boost::bind( ReturnValueAsShared< std::vector< std::string > >,
                        foo );
  f();

} // main


10 commentaires

Veuillez simplifier le problème et fournir un code d'exemple minimal (non) de travail.


@Kerreksb the erreur est std :: vecteur ne fournit pas d'opérateur d'appel lorsque j'essaie de l'utiliser comme retourvalueasshared > .


@Konradrudolph Je vais essayer de le minimiser.


@KonRADRUDOLPH Cas d'essai ajouté.


Le paramètre boost :: fonction func - peut-être qu'il devrait avoir t au lieu de t () ?


@ user1071136 Non, ce qui échoue à compiler également (comme il le devrait), car ce n'est pas la façon dont la fonction de boost :: La fonction accepte les définitions de la fonction. Voir Boost.function Docs.


HM, on dirait que le boost n'est tout simplement pas si bon. La version std de cela fonctionne dès que vous ajoutez une conversion explicite sur std :: Fonction > ()> autour du lier appel.


@Kerreksb es-tu en train de dire que c'est un bug de boost? Je m'appuyais vers cette conclusion ...


@Kerreksb j'ai essayé d'envelopper le deuxième appel appel avec boost :: Fonction ()> () pour le jeter et il compile. Kerrek, faites votre commentaire une réponse et je vais l'accepter car cela m'a conduit sur le chemin droit (je viens d'utiliser la version boost :: de ce que vous avez dit).


Comportement étrange ... LiveWorkspace.org/code/2C2B09F708A6D481E06AA39F2EDA632F compilateur Essayez de convertir Int à Boost :: Fonction .


3 Réponses :


2
votes

la réécriture complète, la réponse originale était incorrecte.

analyse d'erreur

Comme je ne savais pas au début ce qui se passait ici, j'ai fait une analyse. Je le garde pour une référence future; Voir la solution ci-dessous pour éviter le problème.

bind.hpp est-ce: xxx

qui à mon avis Traduit comme suit: xxx

Donc, de sorte que ce que vous attendez que ce code fasse est de transmettre l'argument à la fonction, juste comme ça. Mais pour que cela fonctionne, l'expression a [base_type :: a1 _] devrait être de type bottes: _bi :: valeur , alors que c'est de la Type non emballé Boost :: _ BI :: BIND_T . Donc, au lieu du fonctionnement étant passé comme argument, une version surchargée spéciale est appelée: xxx

Ceci sera évaluer la fonction nullaire, au lieu de passer sur. Donc, au lieu d'un objet renvoyant un vecteur, l'argument est maintenant un Vecotr. Les étapes suivantes tenteront de convertir cela en une fonction boost :: fonction et échouer.

solution canonique

édité à nouveau: de
Il ressemble à cette manipulation spéciale de Lié imbriquée est conçu comme une fonctionnalité. Parler sur #Boost avec les utilisateurs ZAO et Heller, je sais maintenant qu'il existe une fonction protège pour contrer ces effets. Donc, la solution canonique à ce problème semble être la suivante: xxx


7 commentaires

Non, la valeur renvoyée est un foncteur qui, lorsqu'il est exécuté renvoie un partagé_ptr . Si je remplace f () avec (* f) () , je reçois à juste titre une erreur de compilateur qui se plaint que f n'est pas de type pointeur .


Ok, vous êtes rythmé, le problème est un niveau plus profond. Il me semble que Bind n'a pas de surcharge pour partagé_ptr , il suppose donc un objet de fonction par défaut. Mais comme partagé_ptr ne fournit pas d'opérateur d'appel, les choses échouent.


Um, Bind n'a pas besoin d'une surcharge pour partagé_ptr , c'est un modèle. En outre, l'erreur se plaint que vecteur n'a pas d'opérateur d'appel, pas un partagé_ptr .


Pour votre version modifiée: il semble manquer qu'il y a un boost :: lid ( devant retourvalueasshared dans auto f = ... . En tout point, le code essaie d'appeler partagé_ptr <...> :: opérateur () .


OK, que sur le vecteur est un bon point. Je vais laisser ma réponse pour le moment, comme une documentation d'efforts qui échoua, mais vous attendez à la supprimer éventuellement une fois une réponse appropriée.


@LUCAS: Deuxième match majeur, réécrit complètement le code. Obtenu ça marche.


@LUCAS, j'ai encore modifié la réponse; Maintenant, il inclut la solution canonique conçue dans la documentation de Boost.



2
votes

Certaines constructions (telles que lidez ) renvoient des types intermédiaires "expression" que vous ne voulez réellement capturer sur le nez. Dans ce cas, vous ne devez pas capturer le type via auto et vous devrez peut-être spécifier des conversions explicites, car sinon il n'y a pas une chaîne de conversion unique unique à l'utilisateur unique. Dans votre cas, ajoutez la conversion explicite de l'expression de liaison à la fonction : xxx

(ceci elle-même ne fonctionne pas pour moi, mais ça marche si vous Utilisez les constructions correspondantes std .)


1 commentaires

Emballage mon deuxième Bind Appelez avec un casting boost :: Fonction ()> (...) fait tout ce qui fonctionne. Merci pour l'info.



3
votes

Boost :: Protéger est la voie à suivre:

int main()
{
  auto f = boost::bind( ReturnValueAsShared< std::vector< std::string > >,
                        boost::protect(boost::bind( foo, std::string("a") ) ) );
  f();

} // main


1 commentaires

Cette réponse pourrait être améliorée par une explication de ce que boost :: protège est ce qu'il fait et peut-être un lien vers les documents qui le décrivent encore plus en détail.