我正在尝试使用两个eachPixel函数。一个返回图像,另一个没有返回。我得到了#each;对eachPixel的调用含糊不清"即使我正在指定lambda的返回类型。
如何解决歧义?
// this one does not return an image
void eachPixel(const QImage &image, const std::function <void (uint)>& pixelFunc, const QRect &bounds=QRect()) {
...
for (int y=region.y(); y<=region.bottom(); y++) {
for (int x=region.x(); x<=region.right(); x++) {
pixelFunc(image.pixel(x,y));
}
}
}
// This one returns an image
QImage eachPixel(const QImage &image, const std::function <uint (uint)>& pixelFunc, const QRect &bounds=QRect()) {
...
QImage out(image.size(), image.format());
for (int y=region.y(); y<=region.bottom(); y++) {
for (int x=region.x(); x<=region.right(); x++) {
out.setPixel(x,y, pixelFunc(image.pixel(x,y)));
}
}
return out;
}
void test_pixelFunc() {
QImage image(300,200, QImage::Format_ARGB32);
image.fill(Qt::blue);
QImage out = eachPixel(image, [] (uint p) -> uint { //uint specified!!
return qRgb(qRed(p), qBlue(p), qGreen(p)); // swap green and blue channels
}, QRect (0,0, 300, 200));
out.save("test_pixelfunc.png");
int accumulator=0;
eachPixel(image, [&accumulator](uint p) -> void { // void specified!
accumulator++;
}, QRect (0,0, 300, 200));
qDebug() << "accumulator" << accumulator;
};
答案 0 :(得分:2)
您可以将ignore参数添加到lambdas之一以帮助解决歧义:
struct noreturn_tag {};
void foo( std::function<void(int,noreturn_tag)>);
void foo( std::function<int(int)>);
int main() {
foo( []( int ) { return 0; } );
foo( []( int, noreturn_tag ) {} );
}
答案 1 :(得分:1)
您可以在传入的函数的返回类型上使用模板和SFINAE。
#include <iostream>
#include <functional>
template <typename T, std::enable_if_t<std::is_same_v<void, decltype(std::declval<T>()(1))>, int> = 0>
void foo (T f) {
// std::function<void(int)> func = f;
// if you really need a std::function
f(1);
}
template <typename T, std::enable_if_t<std::is_same_v<int, decltype(std::declval<T>()(1))>, int> = 0>
int foo (T f) {
return f(1);
}
int main() {
foo([](int x) { std::cout << "void " << x << '\n'; });
foo([](int x) { std::cout << "int\n"; return x; });
}
对于c ++ 11,您可以直接使用std::is_same
和std::enable_if
。
template <typename T, typename std::enable_if<std::is_same<void, decltype(std::declval<T>()(1))>::value, int>::type = 0>
void foo (T f) {
f(1);
}
template <typename T, typename std::enable_if<std::is_same<int, decltype(std::declval<T>()(1))>::value, int>::type = 0>
int foo (T f) {
return f(1);
}