C++20現在の言語仕様では、ラムダ式に対して(普通のプログラマが期待するであろう)属性指定は行えない。C++2b(C++23)に向けた提案(PDF)P2173R0が進行中。
2022-02-17追記:2022年2月会合にてC++2b(C++23)へ提案文書(PDF)P2173R1が採択された。
下記コードはC++構文規則上は許容されるものの、ラムダ式の戻り値に対するnodiscard属性指定ではなく、ラムダ式により生成されるクロージャクラスClosure
の関数呼び出し演算子オーバーロード関数型int Closure::operator()() const
に対する属性指定と解釈される。
// C++20: ラムダ戻り値にnodiscard属性を指定 ?? auto lm = [] () [[nodiscard]] { return 42; }; // GCC 11.0/-std=c++2a // warning: 'nodiscard' attribute can only be applied to functions or to class or enumeration types // Clang 11.1/-std=c++2a // error: 'nodiscard' attribute cannot be applied to types
C++2bにおけるラムダ式戻り値に対する属性指定は、パラメータ宣言部の直前に記述する構文となる予定。C++11~C++20現在の関数型に対する属性指定*1はそのまま維持される。
// C++2b: ラムダ戻り値にnodiscard属性を指定 auto lm = [] [[nodiscard]] () { return 42; }; // ^^^^^^^^^^^^^ std::integral auto f = /*...*/; // C++2b: ジェネリックラムダ戻り値にnodiscard属性を指定 auto glm = [f] <typename T> requires std::integral<T> [[nodiscard]] (T n) mutable noexcept -> T { return n * f++; }; // ^^^^^^^^^^^^^
おまけ:GCC 9.3以降では上記C++2b構文が期待通りに解釈される(言語バージョン指定-std=c++NN
は不問)。GCC Bugzilla 90333 によれば意図的な仕様拡張か?Clang 13ではC++2b以降の仕様である旨が表示される*2。
関連URL