2014-06-22 2 views
1

Je dois faire fonctionner ces fonctions dans la syntaxe "normale". comment puis-je le changer? En fait, j'ai besoin de changer la fonction "for_each" qu'elle utilisera en dehors de la classe. Je ne sais pas comment le faire. pouvez-vous aider?comment se débarrasser de la syntaxe lambda

+4

Vous pourriez il suffit de faire du lambda un foncteur exactement comme le standard le définit de toute façon dans [expr.prim.lambda]. – chris

+0

Avez-vous essayé de le faire? Comprenez-vous comment fonctionne la version actuelle du code? – Ilya

+0

Je ne vous comprends pas vraiment. Je ne sais pas comment ce coude fonctionne donc je serais heureux d'avoir une explication. mais mon professeur m'a demandé de changer ce code de toute façon à une syntaxe normale. – user144555

Répondre

3

Une fonction lambda est une fermeture de type, implémentée en tant que foncteur sans nom.

Vous pouvez consulter ces mots clés pour comprendre comment effectuer une "conversion". Quasiment la règle serait que cette lambda:

[capture_clause](args) -> return_type { /* lambda_body */ } 

est pratiquement (dans une vue simplifiée - lambdas générique ou valeur/ref captures ne sont pas explicitement montré ici) ce

struct no_name 
{ 
    no_name(capture_clause) : /* Initialize the closure */ { } 
    return_type operator()(args) { /* lambda_body */ } 
}; 

Dans votre cas, vous auriez à faire une classe comme suit:

template <template <class, class> class Container> 
struct lamda_fun 
{ 
    Container<Course*, std::allocator<Course*> > &newone; 

    lamda_fun(Container<Course*, std::allocator<Course*> > &newone) 
     : newone(newone) { 
    } 
    void operator()(Course *c) { 
     Course* nc = new Course(c->getName(),c->getNumber(), c->getFaculty());  
     newone.push_back(nc); 
    } 
}; 

Si vous voulez toujours vous débarrasser de la syntaxe lambda appeler comme

std::for_each(courses.begin(), courses.end(), lamda_fun<Container>(newone)); 

Même si une copie du foncteur sera transmis à for_each, le foncteur enveloppe une référence sera donc fait la bonne chose.


Une façon plus facile serait de simplement utiliser une boucle for bien (oui ceux qui existent encore)

// range based version 
for (auto c : courses) { 
    Course* nc = new Course(c->getName(), c->getNumber(), c->getFaculty());  
    newone.push_back(nc); 
} 

// traditional version 
for (auto it = courses.begin(), ite = courses.end(); it != ite; ++it) 
{ 
    auto c = *it; 
    Course* nc = new Course(c->getName(), c->getNumber(), c->getFaculty());  
    newone.push_back(nc); 
} 
+0

merci, mais comment puis-je changer la fonction que j'ai posté? – user144555

+2

@ user144555 En faisant * exactement * ce que dit cette réponse: créez un foncteur qui implémente 'operator()' correctement, puis passez une instance de ce foncteur à votre algorithme. (+1, btw). – WhozCraig

+0

merci! Je ne sais pas pourquoi, mais le compilateur dit que quelque chose ne va pas avec la défenition du container ("Container n'est pas un template"). Comment je le répare? – user144555

1

Vous pouvez remplacer le lambda avec une classe locale:

#include <algorithm> 
#include <iostream> 
#include <vector> 

template <class Container> 
Container transform(const Container& container) { 

    struct Lambda { 
     Container& result; 
     Lambda(Container& result) : result(result) {} 
     void operator() (const typename Container::value_type& value) { 
      result.push_back(value + 1); 
     } 
    }; 

    Container result; 
    std::for_each(container.begin(), container.end(), Lambda(result)); 
    return result; 
} 

int main() { 
    std::vector<int> u; 
    u.push_back(0); 
    u.push_back(1); 
    u.push_back(2); 
    std::vector<int> v = transform(u); 
    std::cout << v[0] << v[1] << v[2] << '\n'; 
} 
Questions connexes