我一直都这么问,但我从来没有得到过一个非常好的答案; 我认为,在写第一个"Hello World"之前,几乎所有程序员都遇到过"宏不应该使用宏","宏是邪恶的"这样的短语等等,我的问题是:为什么?有了新的C++ 11,这么多年后还有一个真正的选择吗?
简单的部分是关于宏#pragma,特定于平台和特定于编译器,并且大多数时候它们具有严重的缺陷,例如#pragma once在至少两种重要情况下容易出错:不同路径中的相同名称以及一些网络设置和文件系统.
但总的来说,宏的用法和替代品呢?
以下代码不能在 clang 中编译(在 GCC 中可以):
struct A{
int a;
};
auto test(){
constexpr A x{10};
return []{
return x; // <-- here x is A: clang doesn't compile
}();
}
Run Code Online (Sandbox Code Playgroud)
Clang 的错误是变量 'x' 不能在没有指定捕获默认值的 lambda 中隐式捕获,但我认为 constexpr 变量总是被捕获。
如果 x 是 int,则代码编译:
auto test(){
constexpr int x{10};
return []{
return x; // <-- here x is int: clang is ok
}();
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,以下代码也可以编译:
auto test(){
constexpr A x{10};
return []{
return x.a;
}();
}
Run Code Online (Sandbox Code Playgroud)
叮当正确吗?如果是这样,理由是什么?我正在使用 -std=c++17
- 编辑 …
GCC并Clang编译以下代码:
void Test()
{
constexpr int Size = 3;
auto Lambda = [Size]{ int Dim[Size]; };
}
Run Code Online (Sandbox Code Playgroud)
但是,VisualStudio 2015 CTP 6没有.尽管如此,所有3个编译器都对此代码感到满意:
void Test()
{
static constexpr int Size = 3;
auto Lambda = []{ int Dim[Size]; };
}
Run Code Online (Sandbox Code Playgroud)
哪个片段实际上是以正确的方式进行的?C++标准说什么?
以下函数有效(从 C++20 开始):
void foo() {
constexpr const int b { 123 };
constexpr const auto l1 = [](int a) { return b * a; };
(void) l1;
}
Run Code Online (Sandbox Code Playgroud)
即使l1不捕获任何内容,据说它仍然可以“无捕获捕获” 的值b,因为它是 a const(它甚至不必是constexpr;但请参阅@StoryTeller 的评论)。
但如果我尝试在新的 lambda 中捕获更复杂的东西:
void foo() {
constexpr const int b { 123 };
constexpr const auto l1 = [](int a) { return b * a; };
(void) [](int c) { return l1(c) * c; };
}
Run Code Online (Sandbox Code Playgroud)
这无法编译。为什么?l1编译器从 …