迭代器内部的lambda函数

14

使用lambda表达式作为下标运算符似乎在g++和clang中无法工作。

这是实现错误还是C++标准中的“不规范”规则?

示例:

class A
{   
    public:
        template<typename T> void operator[](T) {}
        template<typename T> void operator()(T) {}
};  

int main()
{   
    A a;
    a[ [](){} ];    // did not compiler: see error message
    a( [](){} );    // works as expected
} 

错误:

main.cpp:13:6: error: two consecutive '[' shall only introduce an attribute before '[' token
     a[ [](){} ];
      ^   
main.cpp:13:15: error: expected primary-expression before ']' token
     a[ [](){} ];

我知道属性以 "[[" 开头,但我想知道是否 "[ ["(带一个或多个空格)也可以像这样使用:

 void func( int x [ [gnu::unused] ] ) {} // compiles fine! :-(
3个回答

7

你需要把lambda表达式用括号括起来。否则编译器会将两个[[视为引入属性。

使用operator delete时可能会出现类似的问题。例如,你需要写成:

delete ( [] { return ( new int() ); }() );

或者

delete [] ( [] { return ( new int[10] ); }() );

你需要将lambda用括号括起来。

很高兴看到来自其他背景的这些好奇的例子。谢谢。 - Klaus

4
这在[dcl.attr.grammar]中有详细说明。如果有两个连续的[,则会被视为属性,因此您需要将其括在括号内或者采取其他措施来明确您的意图:

Two consecutive left square bracket tokens shall appear only when introducing an attribute-specifier or within the balanced-token-seq of an attribute-argument-clause. [ Note: If two consecutive left square brackets appear where an attribute-specifier is not allowed, the program is ill-formed even if the brackets match an alternative grammar production. —end note ] [ Example:

int p[10];
void f() {
  int x = 42, y[5];
  int(p[[x] { return x; }()]);   // error: invalid attribute on a nested
                                 // declarator-id and not a function-style cast of
                                 // an element of p.
  y[[] { return 2; }()] = 2;     // error even though attributes are not allowed
                                 // in this context.
  int i [[vendor::attr([[]])]];  // well-formed implementation-defined attribute.
}

—end example ]


1
“Consecutive” 的意思是带有或不带有额外的空格? - Klaus
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Barry
1
昨天我学到了template <> double B::var<double>=1.123;是无效的,但是template <> double B::var<double> =1.123;是有效的。只有一个空格... :-) - Klaus
1
@Klaus >= 也是一个标记。 - Barry

1
你可以用括号将参数包起来。
a[ ( [](){} ) ];

现在没有头绪:-):很高兴看到一个解决方法。但是,有人知道这是否符合标准?将属性的起始位置修正为“[[”可以消除这个问题。这就是我问它是否是破损实现还是“不幸”的标准的原因。 - Klaus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接