我在尝试实现SFINAE欺骗时偶然发现了以下情况(实际上我试图实现的是无关紧要的,我不想理解这种行为):
我定义了一个constexpr函数,该函数引用大小为1的数组,但通过lambda调用指定数组大小:
constexpr bool f(const char(&)[+[](){return 1;}()]) {
return true;
}( lambda之前的+是因为编译器抱怨连续两个左括号。)
我添加了一个调用函数:
constexpr bool g() {
char x[1] = {};
return f(x);
}这汇编得很好。
现在我尝试并实例化:
template<typename T>
constexpr bool f(const char(&)[+[](){return 1;}()]) {
return true;
}
constexpr bool g() {
char x[1] = {};
return f<int>(x);
}这一次我得到了一个奇怪的编译器错误:
ERROR: maps/suggest/indexer/nhr/nhr_flume_flags.cc:134:45 no matching function for call to 'f'
constexpr bool g() { char x[1] = {}; return f<int>(x); }
^~~~~~~
maps/suggest/indexer/nhr/nhr_flume_flags.cc:130:16 candidate function [with T = void] not viable: no known conversion from 'char[1]' to 'const char[+[]() {
return 1;
}()]' for 1st argument
constexpr bool f(const char(&)[+[](){return 1;}()]) { return true; }
^
1 error generated.我为什么要犯这个错误?
我使用的命令是:/usr/lib/llvm-11/bin/clang++ -stdlib=libstdc++ -std=c++17 myprog.cc
编译器的版本信息是:
Debian clang version 11.1.0-4+build3
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-11/bin发布于 2022-03-31 14:00:05
,为什么我会收到这个错误?
/usr/lib/llvm-11/bin/clang++ -stdlib=libstdc++ -std=c++17 myprog.cc
在C++17中不允许在函数签名中使用lambda:
expr.prim.lambda
lambda表达式是一个prvalue,其结果对象称为闭包对象。-表达式不应在未计算的操作数中、模板参数中、别名声明中、类型胡枝子声明中,或在函数或函数模板的声明中,在函数体和默认参数之外出现。注意:的目的是防止lambdas出现在签名中。 - 尾注
这个节目的格式不正确.诊断信息还有改进的余地。不诊断非模板是编译器的错误。
使用常量是很容易的。读起来也容易得多:
constexpr inline auto s = [](){return 1;}();
template<typename T>
constexpr bool f(const char(&)[s])由于提议P0315,应该在C++20中允许它,因为突出显示的规则部分被删除了。然而,Clang仍然无法在C++20中编译它,据我所知,这是一个bug。目前,Clang对P0315的支持被列为“部分”。
https://stackoverflow.com/questions/71693714
复制相似问题