2010-02-26 10 views
3

Cette première partie a été résolue par les commentaires d'Eric ci-dessous mais a conduit à un problème secondaire que je décris après la règle horizontale. Merci Eric! J'essaie de passer un foncteur qui est une classe basée sur un modèle à la méthode create_thread de la classe boost thread_group avec deux paramètres au foncteur. Cependant, je n'arrive pas à dépasser mon erreur de compilation actuelle. Avec le code ci-dessous:Foncteur basé sur le modèle C++ dans l'expression lambda

#include <boost/lambda/lambda.hpp> 
#include <boost/lambda/bind.hpp> 
#include <boost/thread.hpp> 
#include <vector> 

using namespace boost::lambda; 
using namespace std; 

namespace bl = boost::lambda; 

template<typename ftor, typename data> 
class Foo 
{ 
public: 
    explicit Foo() 
    { 
    } 
    void doFtor() 
    { 
     _threads.create_thread(bind(&Foo<ftor, data>::_ftor, _list.begin(), _list.end())); 
     //_threads.create_thread(bind(_ftor, _list.begin(), _list.end())); 
     _threads.join_all(); 
    } 

private: 
    boost::thread_group _threads; 
    ftor _ftor; 
    vector<data> _list; 
}; 

template<typename data> 
class Ftor 
{ 
public: 
    //template <class Args> struct sig { typedef void type; } 

    explicit Ftor() {} 

    void operator() (typename vector<data>::iterator &startItr, typename vector<data>::iterator &endItr) 
    { 
     for_each(startItr, endItr, cout << bl::_1 << constant(".")); 
    } 
} 

J'ai aussi essayé typedef-ing « type » que je pensais que mon problème pourrait avoir quelque chose à voir avec le Sig modèle que le foncteur lui-même est basé sur un modèle.

L'erreur que je reçois est:

error: no matching function for call to ‘boost::lambda::function_adaptor<Ftor<int> Foo<Ftor<int>, int>::*>::apply(Ftor<int> Foo<Ftor<int>, int>::* const&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int>> >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)’ 

avec un tas de préambule au préalable.

Merci d'avance pour toute aide!


D'accord, je l'ai modifié le code de prendre dans les suggestions de Eric ci-dessous pour résultat le code suivant:

#include <boost/lambda/lambda.hpp> 
#include <boost/lambda/bind.hpp> 
#include <boost/thread.hpp> 
#include <vector> 

using namespace boost::lambda; 
using namespace std; 

namespace bl = boost::lambda; 

template<typename ftor, typename data> 
class Foo 
{ 
public: 
    explicit Foo() 
    { 
    } 
    void doFtor() 
    { 
     _threads.create_thread(bl::bind(boost::ref(_ftor), _list.begin(), _list.end())); 
     _threads.join_all(); 
    } 

private: 
    boost::thread_group _threads; 
    ftor _ftor; 
    vector<data> _list; 
}; 

template<typename data> 
class Ftor 
{ 
public: 
    typedef void result_type; 

    explicit Ftor() {} 

    result_type operator() (typename vector<data>::iterator &startItr, typename vector<data>::iterator &endItr) 
    { 
     for_each(startItr, endItr, cout << bl::_1 << constant(".")); 
     return ; 
    } 
}; 

Cependant il en résulte une compilation erreur:

/usr/local/include/boost/lambda/detail/function_adaptors.hpp:45: error: no match for call to ‘(Ftor<int>) (const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)’ 
ftor.h:41: note: candidates are: void Ftor<data>::operator()(typename std::vector<data, std::allocator<_CharT> >::iterator&, typename std::vector<data, std::allocator<_CharT> >::iterator&) [with data = int] 
/usr/local/include/boost/lambda/detail/function_adaptors.hpp:45: error: return-statement with a value, in function returning 'void' 

Il semble avoir void défini comme result_type attend maintenant l'opérateur() pour retourner quelque chose. J'ai essayé de renvoyer result_type à partir de la fonction, mais cela a également généré des erreurs. Des idées?

+1

Quel compilateur que vous utilisez et quelle version de boost? Ici compile bien, sauf que l'en-tête iostream est manquant (GCC 4.3.3, boost 1.42) – coelhudo

+0

Intéressant. J'ai essayé ceci sur mon Mac, pas sûr de la version de gcc là-dessus mais il emploie le coup de pouce 1.42. Et j'ai reproduit sur ma boîte de linux qui utilise des versions légèrement plus anciennes: gcc 4.1.1 et boost 1.37 – Demps

+0

Le code tel que montré compile, mais en instanciant 'Foo :: doFtor()' provoque des erreurs de compilation.Par exemple, essayez d'ajouter 'int main() {Foo , int> f; f.doFtor(); '' –

Répondre

0

Sig (ou dans votre cas, il suffit de typedef void result_type; est nécessaire.

IIRC, lambda :: bind fait des copies const de ses arguments.

Il existe donc un problème avec foncteurs avec opérateur non-const (). Ceci est résolu en faisant Ftor :: operator() const ou en enveloppant (en doFtor()), _ftor avec boost :: ref

Il y a un problème similaire avec les itérateurs. aluminuim boost :: ref ici ne fonctionnera pas directement parce qu'il finirait par utiliser un refere nce à un temporaire. La solution la plus simple est de modifier Ftor :: operator() pour prendre ses arguments par copy.

Le plus simple est donc de modifier Ftor de telle sorte que son opérateur() est const et prend ses arguments par copie:

void operator() (typename vector<data>::iterator startItr, typename vector<data>::iterator endItr)const 

Si vous ne pouvez vraiment pas faire Ftor :: operator() const , vous pouvez modifier doFtor() comme suit (mais il est encore nécessaire de faire Ftor :: operator() prend ses arguments par copie):

_threads.create_thread(bind(boost::ref(_ftor), _list.begin(), _list.end())); 
+0

Avec les changements mentionnés dans l'option 2 je reçois ce qui suit: - erreur: en passant l'argument 1 de 'const boost :: reference_wrapper boost :: ref (T &) [avec T = __gnu_cxx :: __ normal_iterator < int *, std :: vector >>] ' – Demps

+0

En effet, utiliser boost :: ref sur _list.begin() n'est pas une bonne idée, car il finit par passer une référence à un temporaire. Je vais mettre à jour la réponse –

+0

@Eric: J'ai modifié le code comme vous l'avez suggéré mais cela génère aussi une erreur de compilation. Cette fois avec le type de retour que je crois est en baisse pour le typedef. J'ai modifié la question ci-dessus pour refléter les changements. – Demps