簡體   English   中英

標准對作為模板參數的 char 數組有何看法?

[英]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.

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