c++ - 传递 Lambda 时,Visual Studio 2017 中的什么扩展消除了 "bool"与 "std::function"的歧义?

标签 c++ visual-studio c++11 gcc clang

以下代码在 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 在这种情况下是否只是完全流氓。

最佳答案

这是由两件事的相互作用引起的:

  1. MSVC 的无捕获 lambda 具有许多到函数指针的转换函数 - 每个调用约定一个。因此,通过函数指针将无捕获 lambda 转换为 bool 在 MSVC 中是不明确的。

  2. 不是将这种不明确的转换视为不明确的转换序列as the standard requires , MSVC 将其视为根本没有转换序列,这反过来意味着 bool 重载不可行。这使得 function 重载成为唯一可行的重载。

禁用转换为 bool 的最简单方法是为 lambda 提供捕获或捕获默认值 - 即使它最终没有捕获任何东西,具有捕获默认值也是如此足以禁用到函数指针的转换。

关于c++ - 传递 Lambda 时,Visual Studio 2017 中的什么扩展消除了 "bool"与 "std::function"的歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45582048/

相关文章:

c++ - 如何使用 OpenCV 显示 PGM 图像

c++ - Visual Studio 2012 项目中的 tesseract Remove_Reference 模糊符号

visual-studio - 如何跨多个共享项目和解决方案同步 NuGet 包?

c++ - 查找字母子串

c++ - ={} 和 {} 风格的初始化在 C++11 中是否相同?

c++ - 字符串接受接口(interface)应该是什么样子的?

c++ - 是否应该将整数值传递给浮点用户定义的文字?

c# - 在 C# (Visual Studio) 中折叠所有 #regions only(!)

.net - 为什么重命名文件有时会重构类名,有时不会?

c++ - 在 C++ 中选择在运行时调用的函数