这是此处讨论的后续内容.
以下代码在gcc和clang(实时演示)下编译.//1由于lambda没有捕获任何东西,因此对于该情况而言这是令人惊讶的.对于MCR2lambda返回指针本身的情况,我们得到预期的编译时错误(行// Will not compile).运算符的应用sizeof与返回指针有何不同?
#include <iostream>
#define MCR1(s) \
([]() { return sizeof(s); })()
#define MCR2(s) \
([]() { return s; })()
int main() {
auto *s= "hello world";
auto x1 = MCR1( s ); //1
auto y1 = MCR1( "hello world" );
// auto x2= MCR2( s ); // Will not compile
auto y2= MCR2( "hello world" );
std::cout << x1 << " " << y1 << '\n';
std::cout // << x2 << " "
<< y2 << '\n';
}
Run Code Online (Sandbox Code Playgroud)
编辑:继续讨论这里是另一个例子.令人惊讶的是,标记的行//2现在编译在gcc7(开发版)(现场演示)下.这里的区别在于表达式已被标记constexpr,现在.
#include <iostream>
#define MCR1(s) \
([]() { return sizeof(s); })()
#define MCR2(s) \
([]() { return s; })()
int main() {
auto constexpr *s= "hello world";
auto constexpr x1= MCR1( s );
auto constexpr y1= MCR1( "hello world" );
auto constexpr x2= MCR2( s ); //2
auto constexpr y2= MCR2( "hello world" );
std::cout << x1 << " " << y1 << '\n';
std::cout << x2 << " " << y2 << '\n';
}
Run Code Online (Sandbox Code Playgroud)
不同之处在于(缺乏)上下文评估.sizeof没有评估.
根据N3337(≈C++ 11)
§5.12[expr.prim.lambda]/11
如果lambda表达式具有关联的capture-default及其 复合语句 odr-uses
this或具有自动存储持续时间的变量,并且未明确捕获使用odr的实体,则称该odr-used实体被隐式捕获 ;
和
§5.1.2[expr.prim.lambda]/12
如果lambda表达式使用odr
this或具有自动存储持续时间的变量,则该实体应由其捕获lambda-expression.如果lambda表达式捕获实体并且未在紧邻的lambda表达式或函数中定义或捕获该实体,则该程序格式错误.
ODR使用意味着在潜在的评估环境中使用:
§3.2[basic.def.odr]/2
一个表达式是可能评价,除非它是一个未计算的操作数或它们的子表达式.名称显示为潜在评估表达式的变量是odr-used,除非它是满足出现在常量表达式中的要求的对象,并且立即应用左值到右值的转换
由于sizeof不是,并且s正在达到 lambda表达式的范围,所以没关系.s然而,回归意味着评估它,这就是为什么它形成不良.
Lambda 可以“看到”周围范围内的许多事物,而无需捕获它们:
-- 全局变量:
int x = 42;
int main() { []{ std::cout << x; }(); }
Run Code Online (Sandbox Code Playgroud)
-- 静态局部变量:
int main() {
static int x = 42;
constexpr int y = 1337;
[]{ std::cout << x << y; }();
}
Run Code Online (Sandbox Code Playgroud)
- 功能:
int x() { return 42; }
int main() { []{ std::cout << x(); }(); }
Run Code Online (Sandbox Code Playgroud)
-- 类型:
using x = std::integral_constant<int, 42>;
int main() { []{ std::cout << x::value; }(); }
Run Code Online (Sandbox Code Playgroud)
-- 在未计算的上下文中使用的局部变量:
int main() {
int x = 42;
[]{ std::cout << sizeof(x); }();
}
Run Code Online (Sandbox Code Playgroud)
这自然不符合语言规则。您可以在 C++98 中使用手写的可调用对象执行相同的操作:
int main() {
int x = 42;
struct functor {
int operator()() const { return sizeof(x); }
};
std::cout << functor{}();
}
Run Code Online (Sandbox Code Playgroud)
这并不奇怪,因为sizeof没有评估它的表达式:
int main() {
int x; // uninitialized
using y = std::integral_constant<size_t, sizeof(x)>; // x used in a constant expression
using z = std::integral_constant<size_t, 4>;
static_assert(std::is_same<y, z>::value, "");
std::cout << y::value;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
225 次 |
| 最近记录: |