簡體   English   中英

C++20:非類型模板參數中的非捕獲 lambda

[英]C++20: Non-capturing lambda in non-type template parameter

C++20 是否允許衰減為函數指針的非捕獲 lambda 直接作為非類型模板參數傳遞? 如果是這樣,正確的語法是什么?

我已經使用-std=c++2a在各種版本的 clang 和 gcc 中嘗試了以下代碼。

#include <iostream>

template<auto f>
struct S {
    static void invoke(int x) { f(x); }
};

using X = S<+[](int x) -> void { std::cout << x << " hello\n"; }>;

int main()
{
    X::invoke(42);
}

gcc 毫無怨言地編譯代碼,代碼按預期運行。

clang 編譯失敗並出現以下錯誤:

error: a lambda expression cannot appear in this context
using X = S<+[](int x) -> void { std::cout << x << " hello\n"; }>;
             ^

這是完整的代碼(在線版本):

Clang 10.0.0 頭: https : //wandbox.org/permlink/n5eKQ4kQqSpDpr4k

Gcc 10.0.0 HEAD 20200113: https ://wandbox.org/permlink/vJ44sdMtwCKAFU64

C++20 是否允許衰減為函數指針的非捕獲 lambda 直接作為非類型模板參數傳遞?

是的。

事實上,您可以更進一步——您甚至不需要將 lambda 轉換為函數指針。 您可以只提供 lambda。 這是有效的 C++20:

using Y = S<[](int x) -> void { std::cout << x << " hello\n"; }>;

我們在 C++20 中的規則是現在允許在未評估的上下文中使用 lambdas ( P0315 )。 在那里的許多其他措辭更改中,本文打破了阻止在模板參數中使用 lambda 的規則( C++17 的 [expr.prim.lambda]/2 ):

lambda 表達式不應出現在未計算的操作數、模板參數別名聲明、typedef 聲明中,或者出現在函數體和默認參數之外的函數或函數模板的聲明中。

該子句在 C++20 中不再存在。

取消這個限制允許將 lambda 用作模板參數,並且從無捕獲 lambda 到函數指針的轉換在 C++17 中已經是 constexpr。 clang 還沒有實現這個特性( using T = decltype([]{});在 gcc 上編譯,還沒有在 clang 上編譯)。 我還不會稱其為 clang 錯誤,它只是一個尚未實現的 clang 功能(未評估上下文中的 lambdas 尚未在cppreference 編譯器支持頁面中列出為已實現)。


C++20 非類型模板參數 ( P1907 ) 甚至允許刪除+因為無捕獲的 lambda 算作結構類型( [temp.param]/7 ),因為根本沒有任何數據成員。

如果這方面的規則自 C++17 以來沒有改變,則不允許使用 lambda 作為模板參數,原因與不允許使用字符串文字相同。 每個 lambda 都有不同的類型,每個字符串字面量都指向不同的對象。 C++17 中的變化是閉包對象現在是constexpr 要使用字符串文字或 lambda 作為模板參數,對象必須具有外部鏈接。 所以這在 C++17 中是允許的。

template <auto>
struct S {};

constexpr const char string[] = "String literal";
constexpr auto lambda = []{};

S<string> a;
S<+lambda> b;

閉包對象本身不能用作模板參數(因此您不能執行S<lambda> ),但這可能在 C++20 中通過三向比較發生了變化。 對象必須具有外部鏈接的原因是因為它破壞了模板。 S<+[]{}>S<+[]{}>將被視為不同的類型,即使它們看起來相同(與S<"">類似)。

模板參數必須是constexpr變量。

有一個針對 lambda 的相關提案N4487

我不知道它是否使它成為 C++20。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM