[英]Extra typename keyword in template parameter list: is it valid or not?
[英]Is []<typename>(){} a valid lambda definition?
我正在嘗試使用lambdas和編譯器,因為這里有另外一個問題 。
我剛剛意識到(並且確實非常正常)以下代碼是有效的:
int main() {
auto l = [](){};
l.operator()();
}
實際上標准說閉包類型有一個公共內聯函數調用操作符等等,因此能夠調用它是有意義的。
通過查看標准(以及工作草案)我無法解釋的是,GCC(6.1)編譯了以下代碼段(clang 3.9沒有):
int main() {
auto l = []<typename>(){};
l.operator()<void>();
}
沒有警告,沒有錯誤。 它是有效的代碼還是被編譯器拒絕?
在N4140 5.1.2 [expr.prim.lambda]中,Lambda表達式定義為
lambda-introducer lambda-declarator opt復合語句
其中“lambda-introducer”是[]
,包含可選的“lambda-capture”和“lambda-declarator opt ”是以“(parameter-declaration-clause)”開頭的東西。
[]<typename>(){}
不符合該要求,因為lambda介紹者和lambda聲明符之間存在某種東西,因此它不是有效的lambda表達式。
因此,您的示例代碼不是有效的C ++,應該被編譯器拒絕。
由於這也標記為gcc ,我點擊了GNU C ++擴展列表。 我沒有找到任何可以使GNU C ++中的語法合法的擴展。
然而,根據該提案的第4節(P0428R0),該提議將模板化的lambda添加到C ++中,gcc在2009年得到了上述論文的實驗性實現。這可能解釋了為什么gcc不會在這里抱怨。
它似乎是一個GCC擴展(模板化的lambdas)。
#include <iostream>
int main() {
auto l = []<typename T>(T const& x){ std::cout << __PRETTY_FUNCTION__ << " " << x << std::endl;};
l(42);
l("Hello world");
}
結果是
main()::<lambda(const T&)> [with T = int] 42
main()::<lambda(const T&)> [with T = char [12]] Hello world
給定的代碼格式良好,並且從C ++ 20開始按預期工作。
Per [expr.prim.lambda] :
lambda表達式 :
lambda-introducer lambda-declarator opt復合語句
lambda-introducer<
template-parameter-list>
requires-clause opt lambda-declarator opt compound-statement
最后一行反映了這種語法。 Per [expr.prim.lambda] / 5 :
一個lambda是一個通用的拉姆達 ,如果有一個DECL-說明符是一個占位符型說明符在λ-表達的參數聲明的DECL說明符-SEQ, 或者如果拉姆達具有模板參數列表 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.