使用 lambda 函数签名的函数重载
Function overload using lambda function signature
考虑以下示例
void foo(const std::function<int()>& f) {
std::cout << f() << std::endl;
}
void foo(const std::function<int(int x)>& f) {
std::cout << f(5) << std::endl;
}
int main() {
foo([](){return 3;});
foo([](int x){return x;});
}
这不会编译,因为据说对foo
的调用是不明确的。据我了解,这是因为 lambda 函数不是先验的std::function
,而是必须强制转换为它,并且有一个接受任意参数的std::function
构造函数。
也许有人可以向我解释为什么有人会创建一个采用任意参数的隐式构造函数。但是,我的尖锐问题是是否有解决方法,它允许使用 lambda 函数的函数签名来重载函数foo
。我尝试过函数指针,但这不起作用,因为捕获 lambda 函数不能转换为普通函数指针。
欢迎任何帮助。
C++11,您的编译器是正确的。在 C++14 中,添加了一条规则,指出构造函数模板不得参与重载解析,除非参数的类型实际上可以用std::function
的参数类型调用。因此,此代码应该在 C++14 中编译,而不是在 C++11 中编译。认为这是C++11中的疏忽。
现在,您可以通过显式转换来解决此问题:
foo(std::function<int()>([](){return 3;}));
http://coliru.stacked-crooked.com/a/26bd4c7e9b88bbd0
使用std::function 的替代方法是使用模板。 模板避免了与 std::function 关联的内存分配开销。 模板类型推断机制将推断传递的 lambda 的正确类型,以便调用站点强制转换消失。 但是,您仍然需要消除无参数与参数情况的重载的歧义。
您可以使用行为类似于enable_if的尾随返回类型的技巧来执行此操作。
template<typename Callable>
auto baz(Callable c)
-> decltype(c(5), void())
{
std::cout << c(5) << std::endl;
}
上述 baz 重载仅在可以使用参数 5 调用模板参数 Callable 时才是有效的重载候选项。
您可以在此之上放置更高级的机制以使其更通用(即将参数的可变参数包扩展为可调用),但我想展示基本机制的工作原理。
- 为什么使用SFINAE而不是函数重载
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- c++:可变模板和函数重载
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- 解决模板成员函数重载
- 为什么不允许成员函数和非成员函数之间的函数重载?
- 推断模板化函数中的函数重载
- C++复制函数重载导致"must be a nonstatic member function"错误
- 为什么 std::sort 找不到合适的(静态成员)函数重载?
- 可变参数泛型 lambda 和函数重载
- C++中的函数重载和继承
- 当有右值构造函数可用时,为什么从右值调用类引用构造函数重载?
- C/C++ 可变参数宏函数重载
- 将基类的成员函数重载到其他派生类C++
- C++ 函数重载匹配
- C++函数重载,具体步骤是什么
- C++:使用 param pack 显式调用函数重载
- 隐式生成的函数重载用于右值参数?
- 使用函数重载输入运算符
- 运算符重载函数上的函数重载