如何让std::make_pair与std::bind*兼容?

3
我想要使用std::make_pair,并结合std::bind2nd,以便获得一个一元函数对象,我可以将其与std::transform等函数一起使用。请注意,我现在正在使用的是:
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 ) );

但我想知道 - 是否有更简单的方法使std::make_pair(或可能是任何其他二元函数)可与绑定器一起使用,而不必手动编写像pair_creator这样的小包装类呢?

我需要一个C++03解决方案(出于某种鲜为人知的原因,当我保存帖子时,stackoverflow总是将我的标签重写为)。


1
C++0x是C++11的工作名称,直到几个月前才完成。 - Mike Seymour
@Mike: 啊,我明白了。不知怎么的,我以为 c++0x 标签也应该匹配我的 C++03 问题 :-) - Frerich Raabe
2个回答

4
您需要使用std::ptr_fun,它可以将一个普通的函数指针转换为可调整的二元函数对象(如果您传递一个带有单个参数的函数,则为一元函数对象):
#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被声明为:

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

对于一元版本:

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

你确定在C++11中这是合法的吗?关于为make_pair指定显式模板参数存在一些问题(例如参见此处此处以及此处)... - Kerrek SB
1
@Kerrek:提问者要求C++03解决方案,所以我不确定 :-)。我想对于C++11,您可以使用包装器template <typename T, typename U> std::pair<T,U> backward_compatible_make_pair(T t, U u) return std::make_pair(t,u); }或类似的东西。我认为它应该像旧的C++03 make_pair一样运行。因此,即使在C++11 make_pair移动参数的情况下,它也会复制参数。 - Steve Jessop
啊,太好了。如果没有更好的关于 std::ptr_fun 的讨论,我很快就会接受这个答案,这显然是我想要的。 - Frerich Raabe

-1

使用lambda表达式不需要使用绑定适配器。

    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);
    }

Lambda函数在C++03中不可用(由OP请求)。 - Frerich Raabe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接