Reputation: 931
Hy @ all, we have to realize the following functioncall:
std::mt19937 engine;
color_table lut = create_random_color_map(engine);
The engine has to be exchangeable. We tried to implement it this way:
*.hpp
#include <tuple>
#include <random>
typedef std::tuple<unsigned char,unsigned char,unsigned char> rgb_tuple;
class color_table{
public:
[...]
void generate(rgb_tuple predicate(const unsigned char& index));
};
template <class RANDOM>
static rgb_tuple random_color(RANDOM engine){
std::uniform_int_distribution<int> dist1 (0,255);
unsigned char red = (unsigned char) dist1();
unsigned char green = (unsigned char) dist1(engine);
unsigned char blue = (unsigned char) dist1(engine);
return std::make_tuple(red, green, blue);
}
template <class RANDOM>
static color_table create_random_color_map(RANDOM engine){
color_table lut;
lut.generate([&](const unsigned char& i)->rgb_tuple {
return random_color<decltype(engine)>(engine);
} );
return lut;
}
*.cpp
...
void color_table::generate(rgb_tuple predicate(const unsigned char& index)){
for(int i = 0; i < 256; ++i){
std::tie(red_table[i], green_table[i], blue_table[i]) = predicate(i);
}
}
When we try to compile, the following error occurs:
error C2664: 'color_table::generate': Convertion of the parameter 1 from 'create_random_color_map::' to 'rgb_tuple (__cdecl *)(const unsigned char &)' not possible 1>
No userdefined convertionoperator available, that can execute the convertion or the operator cannot be invoked. ... Function-template "color_table create_random_color_map(RANDOM)". with [
RANDOM=std::mt19937 ]
We are completely clueless about that failure and google isn't our friend in that case! :/
We appreciate any help!
Regards Hymir
Upvotes: 1
Views: 160
Reputation: 126432
First (major) issue:
Your function generate()
accepts a function pointer as its argument, and you are trying to pass a capturing lambda. Unfortunately, capturing lambdas cannot be converted implicitly to function pointers. Per paragraph 5.1.2/6 of the C++11 Standard:
The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.
You could change your design and let generate()
become a function template, accepting a callable object as its argument:
class color_table{
public:
template<typename P>
void generate(P predicate);
};
Alternatively, you could use an std::function
wrapper to achieve flexibility without recurring to templates (but with some run-time overhead):
#include <functional> // <== NEEDED FOR std::function
class color_table{
public:
void generate(std::function<rgb_tuple(const unsigned char&)> predicate);
};
Here is a live example that shows your code compiling with the above solution.
Second (minor) issue:
You should not specify the template arguments for random_color()
explicitly. Rather let the compiler do its job and perform type deduction:
lut.generate([&](const unsigned char& i)->rgb_tuple {
return random_color(engine);
// ^^^^^^^^^^^^^^^^^^^^^
});
Upvotes: 3
Reputation: 98358
I think that the problem is that your:
void generate(rgb_tuple predicate(const unsigned char& index));
should be:
void generate(rgb_tuple (*predicate)(const unsigned char& index));
You cannot pass functions around! Just pointers to functions.
But alas! lambdas can only be converted to pointer-to-functions if they have an empty capture set, and your lambda does not.
So you can try with std::function
:
void generate(std::function<rgb_tuple(const unsigned char& index)> predicate);
PS: A bit of explanation is in order... your error message is:
Convertion of the parameter 1 from 'create_random_color_map::' to 'rgb_tuple (__cdecl *)(const unsigned char &)' not possible
The first part create_random_color_map::
is the VC++ way of telling you that it does not know the type of the object it is trying to convert, but it is something local to create_random_color_map
: that is obviously the lambda itself.
The second part rgb_tuple (__cdecl *)(const unsigned char &)
is simply a pointer to function of the appropriate type.
And the error says that the first cannot be converted to the latter.
Upvotes: 0