Luca Jungla
Luca Jungla

Reputation: 150

Using std::transform to make a vector of pair

I would like to create a vector of pairs starting from a pair of vectors. For example, if A is std::vector A = [1 0 1] and B is std::vector B = [0 1 0], I want a structure std::vector C = [1 0, 0 1, 1 0] where C_i = std::pair(A_i,B_i).

I would avoid for loop through the two vector, so I'm looking for few lines code like std::transform().

I tried the following code:

std::vector<bool> boolPredLabel(tsLabels.size()); 
std::vector<bool> boolRealLabel(tsLabels.size());
std::vector<std::pair<bool,bool>> TrPrPair(tsLabels.size());
std::transform(boolRealLabel.begin(), boolRealLabel.end(), boolPredLabel.begin(), TrPrPair.begin(),std::make_pair());

This lead me to a compiler error:

error: no matching function for call to ‘make_pair()’
std::transform(boolRealLabel.begin(), boolRealLabel.end(), boolPredLabel.begin(), TrPrPair.begin(),std::make_pair());
...
note:   candidate expects 2 arguments, 0 provided
std::transform(boolRealLabel.begin(), boolRealLabel.end(), boolPredLabel.begin(), TrPrPair.begin(),std::make_pair());

The message is clear, but I don't know what pass to the binary operator. I have to admit that I don't have a clear understanding of std::transform() and I've just use it with functor.

Upvotes: 6

Views: 1054

Answers (1)

lubgr
lubgr

Reputation: 38325

The binary operation you pass in doesn't make any sense. std::make_pair is a function template taking two arguments, so neither can you invoke it without these two arguments, nor can it be instantiated like a function object to be passed to std::transform.

Instead, you can explicitly instantiate std::make_pair for the template types in question and pass this as to the algorithm (@RetiredNinja pointed that out but apparently felt too lazy to write an answer):

std::transform(boolRealLabel.cbegin(), boolRealLabel.cend(),
    boolPredLabel.cbegin(), TrPrPair.begin(), std::make_pair<bool, bool>);

Two other options commonly seen are a lambda,

std::transform(boolRealLabel.cbegin(), boolRealLabel.cend(), boolPredLabel.cbegin(),
    TrPrPair.begin(), [](bool a, bool b){ return std::make_pair(a, b); });

or a pointer to a function

std::pair<bool, bool> toPair(bool a, bool b)
{
    return std::make_pair(a, b);
}

std::transform(boolRealLabel.cbegin(), boolRealLabel.cend(),
    boolPredLabel.cbegin(), TrPrPair.begin(), toPair);

And for completeness, cppreference on std::transform and its binary operation argument (only relevant to the overload that acts on two input ranges):

binary_op - binary operation function object that will be applied.

The signature of the function should be equivalent to the following:

Ret fun(const Type1 &a, const Type2 &b); 

Upvotes: 7

Related Questions