1

Hy@all,我们要实现如下函数调用:

std::mt19937 engine;
color_table lut = create_random_color_map(engine);



发动机必须是可更换的。我们尝试以这种方式实现它:
*.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);
    }
}

当我们尝试编译时,会出现以下错误:

错误 C2664: 'color_table::generate': 参数 1 从 'create_random_color_map::' 到 'rgb_tuple (__cdecl *)(const unsigned char &)' 的转换不可能 1>
没有可用的用户定义转换运算符,可以执行转换或无法调用运算符。... 函数模板“color_table create_random_color_map(RANDOM)”。与 [
随机=std::mt19937]

我们对这次失败完全一无所知,在这种情况下,谷歌不是我们的朋友!:/

我们感谢任何帮助!

问候海米尔

4

2 回答 2

3

第一个(主要)问题:

您的函数generate()接受一个函数指针作为其参数,并且您正在尝试传递一个捕获 lambda。不幸的是,捕获 lambda 不能隐式转换为函数指针。根据 C++11 标准的第 5.1.2/6 段:

没有lambda-capture的lambda 表达式 的闭包类型具有一个公共的非虚拟非显式 const 转换函数,该函数指向具有与闭包类型的函数调用运算符相同的参数和返回类型的函数的指针。这个转换函数返回的值应该是一个函数的地址,当被调用时,它与调用闭包类型的函数调用运算符具有相同的效果。

你可以改变你的设计,让它generate()成为一个函数模板,接受一个可调用对象作为它的参数:

 class color_table{
    public:
        template<typename P>
        void generate(P predicate);
 };

或者,您可以使用std::function包装器来实现灵活性,而无需重复使用模板(但会产生一些运行时开销):

#include <functional> // <== NEEDED FOR std::function

class color_table{
    public:
        void generate(std::function<rgb_tuple(const unsigned char&)> predicate);
};

这是一个实时示例,显示您的代码使用上述解决方案进行编译。

第二个(次要)问题:

您不应random_color()显式指定模板参数。而是让编译器完成其工作并执行类型推导:

lut.generate([&](const unsigned char& i)->rgb_tuple {
    return random_color(engine);
//         ^^^^^^^^^^^^^^^^^^^^^
});
于 2013-05-21T23:15:00.093 回答
0

我认为问题在于您的:

void generate(rgb_tuple predicate(const unsigned char& index));

应该:

void generate(rgb_tuple (*predicate)(const unsigned char& index));

你不能传递函数!只是指向函数的指针。

可惜!如果 lambdas 有一个空的捕获集,而您的 lambda 没有。

所以你可以尝试std::function

void generate(std::function<rgb_tuple(const unsigned char& index)> predicate);

PS:有点解释是为了......你的错误信息是:

无法将参数 1 从 'create_random_color_map::' 转换为 'rgb_tuple (__cdecl *)(const unsigned char &)'

第一部分create_random_color_map::是 VC++ 告诉你它不知道它试图转换的对象的类型的方式,但它是本地的create_random_color_map:显然是 lambda 本身。

第二部分rgb_tuple (__cdecl *)(const unsigned char &)只是一个指向适当类型函数的指针。

错误说第一个不能转换为后者。

于 2013-05-21T23:16:18.130 回答