在 lambda 中,第二个属性列表有什么作用?

Hol*_*Cat 17 c++ syntax lambda c++23 c++-attributes

C++23 允许[[...]]lambda 表达式中的属性:

auto lambda = [] [[nodiscard]]
{
    return 42;
};
Run Code Online (Sandbox Code Playgroud)

但是语法有两个属性列表,大致在参数列表之前和之后:

auto lambda = [] [[nodiscard]] () [[deprecated]]
//               (1)~~~~~~~~~~    (2)~~~~~~~~~~~  // (2) seems to have no effect here
{
    return 42;
};
Run Code Online (Sandbox Code Playgroud)

这两个列表适用于不同的事物,但我无法弄清楚第二个列表的用途,以及我可以在此处放置哪些属性。对于我在 (2) 中尝试的任何属性,Clang 警告:'...' attribute cannot be applied to types

标准是这样说的:

[expr.prim.lambda.closure]/6

... attribute-specifier-seq [位于位置 (2)] 属于相应函数调用运算符或运算符模板的类型。

attribute-specifier-seq [位于位置 (1)] 属于相应的函数调用运算符或运算符模板。

“属于相应函数调用运算符的类型”让我感到困惑。我可以在这里放置哪些属性?这是否仅适用于特定于编译器的属性?如果是,这里可以使用哪些非标准属性?

显然,列表 (2) 早在 C++23 之前就已存在(该提案添加了列表 (1))。

Art*_*yer 17

位置 (2) 处的属性适用于 的类型operator()(这是函数类型),而位置 (1) 处的属性适用于函数声明本身。

没有一个标准属性适用于类型,因此当放入位置 (2) 时,没有标准属性适用。

从https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.htmlhttps://clang.llvm.org/docs/AttributeReference.html#type-attributes查看特定于供应商的类型属性,您可以看到大多数类型属性仅适用于某种类型的对象类型(例如,[[gnu::aligned]][[gnu::vector_size]])。

似乎适用于任何类型(包括函数类型)的一个属性是[[clang::annotate_type(...)]]

// [] [[clang::annotate_type("xyz") () {}  // Error
[] () [[clang::annotate_type("xyz")]] {}
// (For completeness, `clang::annotate` is used for declarations)
[] [[clang::annotate("annotates operator()")]] () [[clang::annotate_type("annotates type of operator(), `void()`")]] {}
Run Code Online (Sandbox Code Playgroud)

可能还有其他适用于函数类型的属性,但我还没有找到它们。

它还完美地反映了常规函数声明中的属性放置:

struct X {
    auto operator() [[clang::annotate("annotates operator()")]] () [[clang::annotate_type("annotates void()")]] {}
};
Run Code Online (Sandbox Code Playgroud)

但是,是的,您通常希望属性应用于函数声明而不是函数类型,因此您永远不必在位置 (2) 处使用属性。