M2t*_*2tM 4 c++ gcc clang visual-studio c++11
以下使用MSVC编译器在Visual Studio 2017中进行编译,但无法在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"; });
}
Run Code Online (Sandbox Code Playgroud)
要解决这个问题,我们可以像这样使用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"; });
}
Run Code Online (Sandbox Code Playgroud)
或者我可以通过引入用户类型而不是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"; });
}
Run Code Online (Sandbox Code Playgroud)
我在这里遇到的问题是我有一个非常重要的游戏项目,我正在尝试在Xcode for iOS中编译.据我所知,我无法获得Visual Studio在所有编译器中展示的相同行为(这将是很好的).因此,我试图编辑我的项目,使其更符合标准.
为了在Visual Studio中执行此操作,因为它是我的主要工作环境,我想知道正在使用哪个非标准扩展以及如何尽可能地禁用它.我可以尝试在Xcode中做到这一点,但对于这个特殊的问题,我发现了一些模棱两可的问题,它一次只能给我一些.
作为一个额外的好奇心,我想知道这个模糊的案例是否有任何标准的提议来解决它,或者在这种情况下Visual Studio是否会完全流氓.
这是由两件事的相互作用引起的:
MSVC的无捕获lambda具有许多转换函数来实现函数指针 - 每个调用约定一个.因此,bool在MSVC 中将无捕获的lambda转换为通过函数指针是不明确的.
正如标准所要求的那样,MSVC 不会将这种模糊转换视为模糊转换序列,而是将其视为根本没有转换序列,这反过来意味着bool过载不可行.这使得function过载成为唯一可行的过载.
禁用转换的最简单方法bool是为lambda提供捕获或捕获默认值 - 即使它最终没有捕获任何内容,捕获默认值足以禁用转换为函数指针.