2017-06-22 31 views
0

對於a similar SO question我想出了以下解決方案:限制傳遞的參數的非暫時性的字符串字面

#include <cstdlib> 

class Literal 
{ 
    public: 

    template <std::size_t N> constexpr 
    Literal(const char (&str)[N]) 
    : mStr(str), 
     mLength(checkForTrailingZeroAndGetLength(str[N - 1], N)) 
    { 
    } 

    template <std::size_t N> Literal(char (&str)[N]) = delete; 

    constexpr operator const char*() const noexcept 
    { 
     return mStr; 
    } 

    constexpr const char* c_str() const noexcept 
    { 
     return mStr; 
    } 

    private: 
    const char* mStr; 
    std::size_t mLength; 

    struct Not_a_CString_Exception{}; 

    constexpr static 
    std::size_t checkForTrailingZeroAndGetLength(char ch, std::size_t sz) 
    { 
     return (ch) ? throw Not_a_CString_Exception() : (sz - 1); 
    } 
}; 

它非常好,但它仍然有可能要創建從自動存儲時間陣列一個文字。我希望在編譯時避免這種情況。下面的例子是未定義行爲:

#include <cstdio> 

static Literal okay() 
{ 
    static constexpr const char okay[] = "okay"; 
    return { okay }; 
} 

static Literal boom() 
{ 
    const char boom[] = "boom"; //Oops, static forgotten 
    return { boom }; // <= How to force a compile error here? 
} 

int main() 
{ 
    printf("%s\n", okay().c_str()); // <= the intended use case 
    printf("%s\n", boom().c_str()); // <= the undefined behaviour 
    return 0; 
} 

它也可以在godbolt compiler explorer找到。是否有可能在編譯時檢測到這個用例並強制編譯錯誤?

+0

你爲什麼不堅持使用該文本操作方式 – Sopel

+0

其實我們使用的文字有一段時間了,從來沒有絆倒在這個陷阱,因爲我們的開發人員通常採取的字面操作方式。另一方面,如果一個開發人員出於任何原因編寫這樣的構造,我寧願在編譯時捕獲它,而不是無盡的調試會話。 –

+1

聽起來你應該只是使應用構造函數的私人和文本操作模板的朋友。 –

回答

0

不,這是不可能的。 okay,boom,以及相同大小的字符串文字都具有相同的類型,並且與表達式無法區分。

相關問題