C++ eachPixel函数调用歧义求解:指定Lambda返回类型仍报错
解决eachPixel重载调用的歧义问题
这个歧义问题的核心在于:编译器无法通过lambda的返回类型自动区分两个eachPixel重载。哪怕你明确指定了lambda的返回类型,lambda本身是匿名 functor 类型,它可以被隐式转换为多个std::function类型(比如返回uint的lambda既可以适配std::function<void(uint)>——返回值会被忽略,也可以适配std::function<uint(uint)>),这就导致编译器不知道该匹配哪个重载版本。
下面是几种简单可行的解决办法:
方法1:显式转换lambda为目标std::function类型
直接告诉编译器你要适配的std::function类型,消除推导的歧义:
// 调用返回QImage的版本 QImage out = eachPixel(image, std::function<uint(uint)>([] (uint p) -> uint { return qRgb(qRed(p), qBlue(p), qGreen(p)); }), QRect(0, 0, 300, 200)); // 调用无返回值的版本 eachPixel(image, std::function<void(uint)>([&accumulator](uint p) -> void { accumulator++; }), QRect(0, 0, 300, 200));
方法2:给两个函数起不同的名字
最直接避免重载歧义的方式,把无返回值的版本改名,比如叫processEachPixel:
// 修改无返回值的函数名 void processEachPixel(const QImage &image, const std::function<void(uint)> &pixelFunc, const QRect &bounds=QRect()) { // 原逻辑保持不变 } // 调用时完全不会有歧义 processEachPixel(image, [&accumulator](uint p) -> void { accumulator++; });
方法3:使用标签分派(Tag Dispatch)
定义专门的标签结构体,通过传入不同标签来明确调用的版本:
// 定义区分用的标签 struct ReturnImageTag {}; struct NoReturnTag {}; // 修改函数,增加标签参数作为第一个参数 void eachPixel(NoReturnTag, const QImage &image, const std::function<void(uint)> &pixelFunc, const QRect &bounds=QRect()) { // 原无返回值版本的逻辑 } QImage eachPixel(ReturnImageTag, const QImage &image, const std::function<uint(uint)> &pixelFunc, const QRect &bounds=QRect()) { // 原返回QImage版本的逻辑 } // 调用时传入标签明确版本 QImage out = eachPixel(ReturnImageTag{}, image, [] (uint p) -> uint { return qRgb(qRed(p), qBlue(p), qGreen(p)); }); eachPixel(NoReturnTag{}, image, [&accumulator](uint p) -> void { accumulator++; });
补充:为什么原来的写法会触发歧义?
对于返回uint的lambda,编译器可以将它转换为std::function<void(uint)>(此时返回值会被自动忽略),也可以转换为std::function<uint(uint)>——这两种转换都是合法的,因此编译器无法确定你要调用哪个重载。而返回void的lambda虽然只能转换为std::function<void(uint)>,但如果编译器在推导时先检查到另一个重载的可能性,也可能误报歧义,所以统一用上面的方法处理就可以解决问题。
内容的提问来源于stack exchange,提问作者user9170
相关产品推荐
相关产品推荐

