2010-04-07 15 views
3

C++ 0x a déconseillé l'utilisation de vieux classeurs tels que bind1st et bind2nd en faveur de std::bind générique. C++ 0x lambdas se lient bien avec std::bind mais ils ne lient pas avec bind1st classique et bind2nd car par défaut lambdas n'ont pas de type typede imbriqué tel que argument_type, first_argument_type, second_argument_type et result_type. Donc je pensais que std::function peut servir comme un moyen standard pour lier lambdas aux anciens liants, car il expose les typedefs nécessaires. Cependant, l'utilisation de std::function est difficile à utiliser dans ce contexte car elle vous oblige à épeler le type de fonction tout en l'instanciant.Utilisation de classeurs obsolètes et C++ 0x lambdas

auto bound = 
    std::bind1st(std::function<int (int, int)>([](int i, int j){ return i < j; }), 10); // hard to use 
auto bound = 
    std::bind1st(std::make_function([](int i, int j){ return i < j; }), 10); // nice to have but does not compile. 

Je ne pouvais pas trouver un générateur d'objet pratique pour std::function. Quelque chose comme std::make_fuction serait bien d'avoir. Est-ce qu'une telle chose existe? Sinon, y a-t-il une autre meilleure façon de lier les lamdas aux liants classiques?

+0

Notez que l'utilisation de classeurs classiques avec lambdas peut être utile pour les bibliothèques héritées qui s'attendent à ce que leurs types d'objets de fonction exposent les typedefs mentionnés ci-dessus. Donc, je ne pense pas que Vanilla Lambdas peut être utilisé avec de telles bibliothèques. – Sumant

Répondre

2

N'a jamais essayé de faire une telle chose, et je n'ai pas le temps de fournir une réponse complète, mais je suppose que quelque chose pourrait être fait avec Boost.FunctionTypes.

Voici un brouillon, incomplet et non testé pour vous donner une idée:

template <typename T> 
struct AdaptedAsUnary : T 
{ 
    namespace bft = boost::function_types; 
    namespace bmpl = boost::mpl; 

    typedef typename bft::result_type<T>::type result_type; 
    typedef typename bmpl::front<typename bft::parameter_types<T>::type>::type argument_type; 

    AdaptedAsUnary(T t) : T(t) {} 
}; 

template <typename T> 
AdaptedAsUnary<T> 
AdaptAsUnary(T t) 
{ 
    return AdaptedAsUnary<T>(t); 
} 
+1

Ceci est une solution soignée. Hériter d'un type lambda est nouveau pour moi et fonctionne bien sur g ++ 4.5. Bien qu'à ce jour, boost :: function_types (1.42) ne supporte pas lambdas comme un type de callable intégré, je pourrais trouver mon chemin. A l'avenir, quand ils le soutiendront (j'espère), cette solution pourra être utilisée telle quelle. Pour l'instant, j'ai utilisé la réponse pour http://stackoverflow.com/questions/2562320/specializing-a-template-on-a-lambda-in-c0x comme un substitut aux capacités d'introspection de boost :: function_types. En utilisant ces fonctions_traits pour lambdas, l'héritage multiple de T et std :: unary_function fonctionne. – Sumant

1

Je ne sais pas pourquoi vous avez encore besoin de la bind1st etc. La seule chose que je pouvais penser est de soutenir l'ancien code . En fait, bind1st(f, a) peut être remplacé par [a](v){ return f(a, v); } etc, et ceci est une solution universelle.