在 C++ 函数模板中,为什么我不能使用 lambda 来指定参数的数组大小?
In a C++ function template, why can't I use a lambda to specify the array size of a parameter?
我在尝试实现一些 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
Why am I getting this error?
/usr/lib/llvm-11/bin/clang++ -stdlib=libstdc++ -std=c++17 myprog.cc
C++17 不允许在函数签名中使用 lambda:
[expr.prim.lambda]
A lambda-expression is a prvalue whose result object is called the closure object. A lambda-expression shall not appear in an unevaluated operand, in a template-argument, in an alias-declaration, in a typedef declaration, or in the declaration of a function or function template outside its function body and default arguments. [ Note: The intention is to prevent lambdas from appearing in a signature. — end note ] [ Note: A closure object behaves like a function object. — end note ]
节目是ill-formed。诊断消息有改进的余地。未诊断 non-template 是一个编译器错误。
使用常量很容易变通。也更容易阅读:
constexpr inline auto s = [](){return 1;}();
template<typename T>
constexpr bool f(const char(&)[s])
自提案 P0315 起,它应该在 C++20 中被允许,因为规则中突出显示的部分已被删除。然而,Clang 仍然无法在 C++20 中编译它,据我所知这是一个错误。目前,Clang 对 P0315 的支持被列为“部分”。
我在尝试实现一些 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
Why am I getting this error?
/usr/lib/llvm-11/bin/clang++ -stdlib=libstdc++ -std=c++17 myprog.cc
C++17 不允许在函数签名中使用 lambda:
[expr.prim.lambda]
A lambda-expression is a prvalue whose result object is called the closure object. A lambda-expression shall not appear in an unevaluated operand, in a template-argument, in an alias-declaration, in a typedef declaration, or in the declaration of a function or function template outside its function body and default arguments. [ Note: The intention is to prevent lambdas from appearing in a signature. — end note ] [ Note: A closure object behaves like a function object. — end note ]
节目是ill-formed。诊断消息有改进的余地。未诊断 non-template 是一个编译器错误。
使用常量很容易变通。也更容易阅读:
constexpr inline auto s = [](){return 1;}();
template<typename T>
constexpr bool f(const char(&)[s])
自提案 P0315 起,它应该在 C++20 中被允许,因为规则中突出显示的部分已被删除。然而,Clang 仍然无法在 C++20 中编译它,据我所知这是一个错误。目前,Clang 对 P0315 的支持被列为“部分”。