为什么编译器不能选择最明显的重载:
#include <iostream>
#include <functional>
static void foo(const std::function<void(bool)>& f) {
std::cerr << "using bool overload" << std::endl;
f(true);
}
static void foo(const std::function<void(int)>& f) {
std::cerr << "using int overload" << std::endl;
f(1);
}
int main() {
foo([](const bool value) {
std::cout << std::boolalpha << value << std::endl;
});
foo([](const int value) {
std::cout << value << std::endl;
});
return 0;
}
你会期望输出:
using bool overload
true
using int overload
1
但是,编译器无法推断出正确的重载:
gcc-4.8
:
main.cpp: In function 'int main()':
main.cpp:17:6: error: call of overloaded 'foo(main()::__lambda0)' is ambiguous
});
^
main.cpp:17:6: note: candidates are:
main.cpp:4:13: note: void foo(const std::function<void(bool)>&)
static void foo(const std::function<void(bool)>& f) {
^
main.cpp:9:13: note: void foo(const std::function<void(int)>&)
static void foo(const std::function<void(int)>& f) {
^
clang-3.4
:
main.cpp:15:5: error: call to 'foo' is ambiguous
foo([](const bool value) {
^~~
main.cpp:4:13: note: candidate function
static void foo(const std::function<void(bool)>& f) {
^
main.cpp:9:13: note: candidate function
static void foo(const std::function<void(int)>& f) {
^
这是因为std::function
构造函数会自动使用和转换参数吗?
答案 0 :(得分:0)
所以为了找到lambda的类型,这很有效:
#include <iostream>
#include <functional>
#include <type_traits>
template<typename F>
struct first_argument {
template<typename Ret, typename A, typename... Rest>
static A helper(Ret (F::*)(A, Rest...));
template<typename Ret, typename A, typename... Rest>
static A helper(Ret (F::*)(A, Rest...) const);
typedef decltype(helper(&F::operator())) type;
};
template <typename T>
static void foo(T f) {
typedef typename first_argument<T>::type type;
std::cerr << "using traits overload" << std::endl;
std::cerr << "typename: " << typeid(type).name() << std::endl;
f(true);
}
template<typename T>
static void foo(void (*f)(const T)) {
std::cerr << "using function pointer overload" << std::endl;
std::cerr << "typename: " << typeid(T).name() << std::endl;
f(T());
}
int main() {
const bool x = false;
foo([](const bool value) {
std::cout << std::boolalpha << value << std::endl;
});
const int i = 9;
foo([i](const bool value) {
std::cout << std::boolalpha << value << ':' << i << std::endl;
});
foo(+[](const bool value) {
std::cout << std::boolalpha << value << std::endl;
});
foo(+[](const int value) {
std::cout << value << std::endl;
});
foo([&x](const bool value) {
std::cout << std::boolalpha << value << '|' << x << std::endl;
});
return 0;
}
运行here
答案 1 :(得分:0)
Lambda可能有一种时髦的语法,但它们仍然是有趣的。也就是说,他们定义了unique_type::operator()(Args...)
。捕获lambda也是如此;捕获的值是lambda对象的成员。
因此,以下代码分解了一个lambda对象:
template<typename T, typename R, typename A>
void bar(T const& t, R (T::*pmf)(A));
template<typename LAMBDA>
void foo(LAMBDA const& l)
{
bar(l, &LAMBDA::operator());
}
显然,如果您只需要在示例中区分两个lambda,则可以用两个非模板化函数替换bar
。 OTOH,如果你需要支持具有任意数量参数的lambda,你需要一个bar
的可变参数模板。