![](/img/trans.png)
[英]What does the C++20 standard say about usage of subojects as template non-type arguments?
[英]What does the standard say about char arrays as template arguments?
在我研究這個問題的答案時,我發現(我之前不知道)gcc 和 clang 允許char
數組作為模板參數,如果它們被聲明為static
。 例如,這段代碼用 gcc 和 clang 編譯:
#include <type_traits>
template <int N, const char (&string)[N]>
auto foo()
{
if constexpr (string[0] == 'i')
return 0;
else
return 3.14f;
}
void bar()
{
static constexpr char string1[] = "int";
static constexpr char string2[] = "float";
auto i = foo<sizeof(string1), string1>();
auto f = foo<sizeof(string2), string2>();
static_assert(std::is_same_v<decltype(i), int>);
static_assert(std::is_same_v<decltype(f), float>);
}
MSVC 也允許這樣做。 但是,要使其與 MSVC 一起使用,我必須在全局命名空間中聲明這兩個字符串。 然后它也能正常工作。
所以我的問題是:標准對此有何看法? 哪個編譯器(如果有)是正確的?
此問題已在 VS 2019 版本 16.4 (msvc v19.24) 中修復: https : //developercommunity.visualstudio.com/content/problem/341639/very-fragile-ice.html
這是從 C++14 到 C++17 的變化,看起來 MSVS 沒有趕上。 以前在[temp.arg.nontype] 中,非類型參數必須是
非類型、非模板模板參數的模板參數應為以下之一:
對於整數或枚舉類型的非類型模板參數,模板參數類型的轉換常量表達式([expr.const]); 或者
非類型模板參數的名稱; 或者
一個常量表達式 ([expr.const]),它指定一個完整的對象的地址,具有靜態存儲持續時間和外部或內部鏈接,或者一個具有外部或內部鏈接的函數,包括函數模板和函數模板 ID,但不包括非靜態類成員,表示(忽略括號)為 & id-expression,其中 id-expression 是對象或函數的名稱,但如果名稱是指函數或數組,則可以省略 &,如果對應的名稱,則應省略模板參數是一個參考; 或者
計算結果為空指針值的常量表達式 ([conv.ptr]); 或者
計算結果為空成員指針值 ([conv.mem]) 的常量表達式; 或者
一個指向成員的指針,如 [expr.unary.op] 中所述; 或者
類型為
std::nullptr_t
的常量表達式。
強調我的
並且由於第 3 條,您不能使用塊作用域變量,因為塊作用域變量根據[basic.link]/10沒有鏈接
這些規則未涵蓋的名稱沒有鏈接。 此外,除非另有說明,在塊范圍內聲明的名稱沒有鏈接。
在 C++17 中,這發生了變化。 [temp.arg.nontype]現在有
非類型模板參數的模板參數應是模板參數類型的轉換常量表達式。 對於引用或指針類型的非類型模板參數,常量表達式的值不得引用(或對於指針類型,不得為以下地址):
一個子對象,
一個臨時對象,
字符串文字,
typeid 表達式的結果,或
預定義的 func__ 變量。
這現在允許您使用塊范圍靜態變量
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.