c++ - C++ lambda 不能正确选择重载函数吗?

标签 c++ visual-c++ lambda c++11 visual-c++-2012

我有一个函数可以遍历容器并将每个元素传递给谓词进行过滤。此函数的重载还将每个元素的索引传递到谓词中。

template<typename TContainer>
void DoSomethingIf(TContainer &c, std::function<bool (const typename TContainer::const_reference)> predicate);

template<typename TContainer>
void DoSomethingIf(TContainer &c, std::function<bool (const typename TContainer::const_reference, int)> predicate);

我发现尝试使用裸 lambda 调用这些函数中的一个会导致 VC11 中的编译器错误,而使用 std::function 对象会成功:

void foo()
{
    std::vector<int> v;

    // fails
    DoSomethingIf(v, [](const int &x) { return x == 0; });

    // also fails
    auto lambda = [](const int &x) { return x == 0; };
    DoSomethingIf(v, lambda);

    // success!
    std::function<bool (const int &)> fn = [](const int &x) { return x == 0; };
    DoSomethingIf(v, fn);
}

1>c:\users\moswald\test.cpp(15): error C2668: 'DoSomethingIf' : ambiguous call to overloaded function
1>          c:\users\moswald\test.cpp(8): could be 'void DoSomethingIf<std::vector<_Ty>>(TContainer &,std::function<_Fty>)'
1>          with
1>          [
1>              _Ty=int,
1>              TContainer=std::vector<int>,
1>              _Fty=bool (const int &,int)
1>          ]
1>          c:\users\moswald\test.cpp(5): or       'void DoSomethingIf<std::vector<_Ty>>(TContainer &,std::function<_Fty>)'
1>          with
1>          [
1>              _Ty=int,
1>              TContainer=std::vector<int>,
1>              _Fty=bool (const int &)
1>          ]
1>          while trying to match the argument list '(std::vector<_Ty>, foo::<lambda_8EADDE04A8D35A3C>)'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>c:\users\moswald\test.cpp(19): error C2668: 'DoSomethingIf' : ambiguous call to overloaded function
1>          c:\users\moswald\test.cpp(8): could be 'void DoSomethingIf<std::vector<_Ty>>(TContainer &,std::function<_Fty>)'
1>          with
1>          [
1>              _Ty=int,
1>              TContainer=std::vector<int>,
1>              _Fty=bool (const int &,int)
1>          ]
1>          c:\users\moswald\test.cpp(5): or       'void DoSomethingIf<std::vector<_Ty>>(TContainer &,std::function<_Fty>)'
1>          with
1>          [
1>              _Ty=int,
1>              TContainer=std::vector<int>,
1>              _Fty=bool (const int &)
1>          ]
1>          while trying to match the argument list '(std::vector<_Ty>, foo::<lambda_8EADDE04A8D35A3D>)'
1>          with
1>          [
1>              _Ty=int
1>          ]

这是意料之中的吗?是否有不同的方法来重载这些函数(没有将一个重命名为“DoSomethingIfWithIndex”?

最佳答案

预计会出现过载歧义。

std::function 有一个可以接受任何参数的转换构造函数模板。只有在构造函数模板被实例化后,编译器才能确定它会拒绝该参数。

在您的第一个和第二个示例中,都需要用户定义的转换来将未指定的 lambda 类型转换为每个 std::function 类型。两种转换都不是更好(它们都是用户定义的转换),因此编译器会报告重载歧义。

在您的第三个示例(有效的示例)中,没有歧义,因为未使用 std::function 构造函数模板。相反,它使用了它的复制构造函数(并且,在所有其他条件相同的情况下,非模板优先于模板)。

关于c++ - C++ lambda 不能正确选择重载函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9339717/

相关文章:

c++ - 简单的拼接代码

c++ - DirectShow 过滤器图在某些机器上永远不会完成

c++ - 在 vs 2010 c++ 中构建 log4cxx

java - 如何使用 jdb 调试 lambda 表达式

c++ - 带参数的嵌入式系统上的最小 C++ 回调

c# - 如何使用 Twincat3 启动/重启 PLC(错误 1793)

c++ - 如何使用 std::accumulate 和 lambda 计算平均值?

lambda - 在 AWS Java SDK 中,我可以在单个包中运行多个处理程序吗?

c++ - 使用 automake 将子目录编译到库中的最佳方法?

c++ - 为什么我会在 MSVC 上收到此警告?