0
votes

I have a type MyStruct which I would like to produce some "sequence" from, where each instance of MyStruct is generated from passing to its constructor an element of another range as well as the output of some function.

The function itself (SomeFun) is a member function in another class, but for this example I'll make it a free function. However, keep in mind that I can's simply place it inside the lambda or do other tricky things to avoid the need for a lambda because I do need to actually pass a this pointer around in my actual case.

Here is 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;                                                                   
}

The output from this is:

main.cpp:31:54: error: could not 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(int)>(((const std::function(int)>*)(& fun)))))))’ from ‘boost::range_detail::transformed_range(int)>, const std::vector >’ to ‘boost::range_detail::transformed_range(int&)>, std::vector >’ return outputs | boost::adaptors::transformed(fun); ^ makefile:25: recipe for target '.obj/main.o' failed

What am I doing wrong here? I don't quot understand why it wants to convert from that type. Any ideas? I'm using Boost 1.55.

1
The error message is completely unreadable. It is missing lots of template arguments. Format it as code rather than a quote.eerorika

1 Answers

4
votes

The error:

test.cpp:29:20: error: no match for ‘operator|’ (operand types are ‘const std::vector’ and ‘std::function >(int)>’) return outputs | fun;

should be perfectly clear. There is no operator| for operands vector and a function. Your second operand should be a boost adaptor which 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));
        };

According to the type declaration, fun should return a MyStruct<Sequence> but your lambda returns a MyStruct<typename Sequence::value_type>. Also, you probably shouldn't hardcode the parameter type as int if the lambda expects a Sequence::value_type. You should probably declare fun as type Converter<Sequence>. Also, fix the parameter type of the lambda and the function to match with Converter (pay attention to the reference).