以下代码在 Visual Studio 2017 中使用 MSVC 编译器编译,但在 GCC 或 Clang 中编译失败。
#include <iostream>
#include <functional>
void functionTest(std::function<void()>) {
std::cout << "F\n";
}
void functionTest(bool) {
std::cout << "B\n";
}
int main() {
functionTest([](){ std::cout << "wut"; });
}
要解决这个问题,我们可以像这样使用 enable_if:
#include <iostream>
#include <functional>
void functionTest(std::function<void()>) {
std::cout << "F\n";
}
template<typename BOOL_TYPE, typename = typename std::enable_if<std::is_same<bool, BOOL_TYPE>::value>::type>
void functionTest(BOOL_TYPE) {
std::cout << "B\n";
}
int main() {
functionTest([](){ std::cout << "wut"; });
}
或者我可以通过引入用户类型而不是 bool 来消除歧义(如果构造函数存在歧义问题,您需要这样做):
#include <iostream>
#include <functional>
void functionTest(std::function<void()>) {
std::cout << "F\n";
}
enum class DescriptiveTypeName {False, True};
void functionTest(DescriptiveTypeName) {
std::cout << "B\n";
}
int main() {
functionTest([](){ std::cout << "wut"; });
}
我在这里遇到的问题是,我有一个非常大的游戏项目,并且正在尝试在 Xcode for iOS 中进行编译。据我所知,我无法获得 Visual Studio 在所有编译器中展示的相同行为(这很好)。因此,我正在尝试编辑我的项目以使其更符合标准。
为了在 Visual Studio 中执行此操作,因为它是我的主要工作环境,我想知道正在使用哪个非标准扩展以及如何尽可能禁用它。我可以尝试在 Xcode 中执行此操作,但对于这个特定问题,我发现了相当多的歧义问题,而且一次只给出了少数几个。
作为一个额外的好奇心,我想知道这个模棱两可的案例是否有任何标准建议来解决它,或者 Visual Studio 在这种情况下是否只是完全流氓。
最佳答案
这是由两件事的相互作用引起的:
MSVC 的无捕获 lambda 具有许多到函数指针的转换函数 - 每个调用约定一个。因此,通过函数指针将无捕获 lambda 转换为
bool
在 MSVC 中是不明确的。不是将这种不明确的转换视为不明确的转换序列,as the standard requires , MSVC 将其视为根本没有转换序列,这反过来意味着
bool
重载不可行。这使得function
重载成为唯一可行的重载。
禁用转换为 bool
的最简单方法是为 lambda 提供捕获或捕获默认值 - 即使它最终没有捕获任何东西,具有捕获默认值也是如此足以禁用到函数指针的转换。
关于c++ - 传递 Lambda 时,Visual Studio 2017 中的什么扩展消除了 "bool"与 "std::function"的歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45582048/