2011-11-16 3 views
3

Je voudrais utiliser std::make_pair utilisable avec par ex. std::bind2nd afin que j'obtienne un objet fonction unaire que je pourrais utiliser avec, par exemple, std::transform.Comment est-ce que je peux utiliser std :: make_pair avec std :: bind *?

En ce moment je suis en utilisant

template <typename T, typename U> 
struct pair_creator : std::binary_function<T, U, std::pair<T, U> > 
{ 
    std::pair<T, U> operator()(T arg1, U arg2) const { 
     return std::make_pair(arg1, arg2); 
    } 
}; 

// ... 

std::transform(start1, end2, start2, std::bind2nd(pair_creator<int, bool>(), true)); 

mais je me demande - est-il un moyen plus facile de faire std::make_pair (ou potentiellement toute autre fonction binaire) utilisable avec les liants, sauf en écrivant petites classes wrapper comme pair_creator par main?

J'ai besoin d'une solution C++ 03 (pour une raison obscure, stackoverflow réécrit toujours ma balise en lors de la sauvegarde du post ...).

+1

C++ 0x était le nom de travail de C++ 11 jusqu'à ce qu'il soit terminé il y a quelques mois. –

+0

@Mike: Ah, c'est logique. Je pensais que la balise 'C++ 0x' devrait aussi correspondre à ma question C++ 03 :-) –

Répondre

4

Vous avez besoin std::ptr_fun, qui transforme un pointeur de fonction ordinaire dans un objet de fonction binaire adaptable (ou un objet de fonction unaire, si vous passez une fonction-arg):

#include <functional> 
#include <utility> 
#include <vector> 
#include <algorithm> 
#include <iostream> 

int main() { 
    std::vector<int> intvec; 
    intvec.push_back(0); 
    intvec.push_back(1); 
    std::vector<std::pair<int,bool> > pairvec(intvec.size()); 
    std::transform(
     intvec.begin(), 
     intvec.end(), 
     pairvec.begin(), 
     // this is the significant line 
     std::bind2nd(std::ptr_fun(std::make_pair<int, bool>), true) 
    ); 
    std::cout << pairvec[1].first << " " << pairvec[1].second << "\n"; 
} 

ptr_fun est déclaré:

template <class Arg1, class Arg2, class Result> 
pointer_to_binary_function<Arg1,Arg2,Result> 
ptr_fun(Result (*)(Arg1,Arg2)); 

Et pour la version unaire:

template <class Arg, class Result> 
pointer_to_unary_function<Arg,Result> 
ptr_fun(Result (*)(Arg)); 
+0

Etes-vous sûr que c'est légitime dans C++ 11? Il y a eu un problème avec la spécification d'arguments de modèle explicites pour 'make_pair' (par exemple [voir ici] (http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/bab04536-8a8d-4b5e-9a49- e10144688667 # b840d54d-d4e9-4602-9273-4118addb8041) et [ici] (http://connect.microsoft.com/VisualStudio/feedback/details/465859/make-pair-generates-c2264) et [ici] (http: //connect.microsoft.com/VisualStudio/feedback/details/691756/std-make-pair-error-in-vc11)) ... –

+1

@Kerrek: questionner a demandé une solution C++ 03, donc non je suis pas certain :-). Je suppose que pour C++ 11, vous pouvez utiliser un wrapper 'template std :: pair backward_compatible_make_pair (T t, U u) return std :: make_pair (t, u); } ', ou quelque chose du genre. Je pense que cela devrait se comporter comme l'ancien C++ 03 'make_pair'. Par conséquent, il copiera l'argument, même dans les cas où le 'make_pair' de C++ 11 le déplacerait. –

+0

+1 Ah, parfait. J'accepterai cette réponse bientôt au cas où personne n'aborderait une meilleure discussion sur 'std :: ptr_fun', ce qui est apparemment exactement ce que je veux. –

-1

L'utilisation de lambda ne nécessite pas d'adaptateur de liaison.

std::vector<int> start1 = list_of(1)(2)(3)(4)(5); 
    std::vector<int> start2 = list_of(10)(20)(30)(40)(50); 
    std::vector<Pair> w_vecofpair; // vector of pair 
    w_vofpair.reserve(start1.size()); 
    // create pair using lambda 
    std::transform(std::begin(start1), std::end(start1), std::begin(start2), // ranges 
     std::back_inserter(w_vecofpair), // result 
     [](int a,int b) { return std::make_pair(a,b);}); // pair creator 

    for (auto& pairInt : w_vecofpair) 
    { 
     std::cout << pairInt << "\n"; 
    } 

    // bind 2nd arg to some value, say 2 
    std::transform(std::begin(start1), std::end(start1), std::begin(start2), 
     std::back_inserter(w_vecofpair), [](int a, int b) { return std::make_pair(a,2);}); 

    for (auto& second : w_vecofpair | map_values) 
    { 
     std::cout << "The second value of our bind 2nd is: " << second << "\n"; 
     assert(second==2); 
    } 
+0

Les fonctions Lambda ne sont pas disponibles en C++ 03 (demandé par l'OP). –

Questions connexes