How do I use boost :: transform to change sequence using lambda in template construction?
I have a type MyStruct
from which I would like to create some "sequence" from which each instance is MyStruct
generated from passing it to the constructor of an element of a different range as well as the output of some function.
The ( SomeFun
) function itself is a member function of another class, but for this example I'll make it free. However, keep in mind that I might just put it inside the lambda, or do other tricky things to avoid the need for the lambda, because I really need to pass a pointer this
in my actual case.
Here's a simplified, testable version to illustrate the problem I'm having:
#include <iostream>
#include <vector>
#include <boost/range/adaptor/transformed.hpp>
#include <functional>
template <typename RowType>
class MyStruct;
template <typename T>
int SomeFun(T t)
{
return 0;
}
template <typename Sequence>
using Converter = std::function<
MyStruct<typename Sequence::value_type>(
typename Sequence::value_type&)>;
template <typename Sequence>
boost::transformed_range<Converter<Sequence>, Sequence>
GenerateTransformedRange(const Sequence& outputs)
{
std::function<MyStruct<typename Sequence::value_type>(int)> fun =
[](const typename Sequence::value_type output)
{
return MyStruct<typename Sequence::value_type>(output, SomeFun(output));
};
return outputs | boost::adaptors::transformed(fun);
}
// some structure
template <typename T>
struct MyStruct
{
MyStruct(T t, int a)
{
}
};
int main(int argc, const char* argv[])
{
std::vector<int> vec {1, 2, 3};
for (auto element : GenerateTransformedRange(vec))
{
}
return 0;
}
Way out of this:
main.cpp: 31: 54: error: failed to convert 'Boost :: range_detail :: operator | (const InputRng &, const boost :: range_detail :: transform_holder &) [with InputRng = std :: vector; UnaryFunction = std :: function (int)>] ((* (const boost :: range_detail :: transform_holder (INT)>
) (& boost :: range_detail :: forwarder :: operator () (T) const [with T = std :: function (int)>; Holder = boost :: range_detail :: transform_holder] (std :: function (intermediate) > (((const std :: function (int)> *) (& fun))))))) from "Upgrade :: range_detail :: transformed_range (intermediate)>, const std :: vector> to" Upgrade :: range_detail :: transformed_range (Int &)>, std :: vector> reverse outputs | boost :: adapters :: converted (fun); ^ makefile: 25: recipe for target .obj / main.o 'failed
What am I doing wrong here? I don't understand why he wants to convert from this type. Any ideas? I am using Boost 1.55
.
source to share
Mistake:
test.cpp: 29: 20: error: no match for operator | (operand types: 'const std :: vector and' std :: function> (int)>) return outputs | fun;
should be perfectly clear. For operands vector
and a, function
no operator|
. Your second operand should be a boost adapter that actually defines the operator. Probably like this:
return outputs | boost::adaptors::transformed(fun);
Also in this code:
std::function<MyStruct<Sequence>(int)> fun =
[](const typename Sequence::value_type output)
{
return MyStruct<typename Sequence::value_type>(output, SomeFun(output));
};
As per the type declaration fun
should return MyStruct<Sequence>
, but your lambda returns a MyStruct<typename Sequence::value_type>
. Also, you probably shouldn't hardcode the type of the parameter as int
if the lambda expects Sequence::value_type
. You should probably declare fun
as a type Converter<Sequence>
. Also, correct the type of the lambda parameter and the function to match Converter
(note the link).
source to share