2011-04-16 71 views
8

我想知道,因爲預定義的文字如ULLf等顯然是在編譯時解決的。標準(2.14.8 [lex.ext])似乎並不限定於此,但它似乎向運行時趨向:用戶定義文字是在編譯時還是運行時解決的?

[2.14.8/2]
用戶定義的字面被視爲對文字操作符或文字操作符模板(13.5.8)的調用。對於 確定這種調用的形式,這種調用對於具有ud-suffix X的給定的用戶定義的文字L,使用非限定名稱的規則在L的上下文中查找其文字後綴標識符爲X的文字操作符ID 查找(3.4.1)。設S是由此查找找到的一組聲明。 S不得空着。
(重點煤礦。)

但是,對我來說這似乎引入不必要的運行時開銷,文字只能被追加到可在編譯時反正像13.37f"hello"_x值(其中_x是用戶定義的文字)。
然後,我們得到了模板化的用戶定義文字,它在標準AFAICS中從未真正定義(即沒有給出示例,請證明我錯了)。這個函數是不是在編譯時被神奇地調用,還是仍然是運行時?

回答

6

是的,你會得到一個函數調用。但函數調用可以是編譯時間常量表達式,因爲文字運算符函數爲constexpr

有關示例,請參閱this one。作爲另一個例子來說明由FDIS允許constexpr計算的高級形式,有編譯時基-26的文字,你可以做

typedef unsigned long long ull; 

constexpr ull base26(char const *s, ull ps) { 
    return (*s && !(*s >= 'a' && *s <= 'z')) ? throw "bad char!" : 
    (!*s ? ps : base26(s + 1, (ps * 26ULL) + (*s - 'a'))); 
} 

constexpr ull operator "" _26(char const *s, std::size_t len) { 
    return base26(s, 0); 
} 

"bcd-"_26將評估擲球入界的表達,從而導致返回值變得不恆定。反過來,它會導致任何使用"bcd-"_26作爲常量表達式變爲格式不正確,並且在運行時拋出任何非常量用法。允許的形式"bcd"_26評估爲相應計算值的常數表達式。

請注意,從字符串文字讀取FDIS不明確允許,但它沒有問題,GCC支持(字符左值引用是常量表達式和字符的值在編譯時已知)。國際海事組織,如果一個人眯眼,可以閱讀FDIS,就好像這是允許的。

然後,我們得到了文字的模板用戶定義的字面,是從來沒有真正的標準AFAICS被定義(即沒有例子說明,請證明我錯了)

治療因爲調用文字操作符模板在2.14.8中定義。你可以在13.5.8找到更多的例子,詳細介紹文字運算符函數/函數模板本身。

該函數在編譯時以某種方式奇蹟般地被調用,還是仍然是運行時?

關鍵字是函數調用替換。見7.1.5。

+0

謝謝,完全忘了'constexpr'。 :)也感謝那一段。 – Xeo 2011-04-16 11:28:23

+0

尋找NUL終止似乎是可疑的,當你交了長度。 – 2013-02-17 00:19:48

0

@Johannes S是正確當然,但我想明確地添加(因爲我面對此),即使對於constexpr用戶定義的文本,所述參數不被認爲constexpr或編譯時間常數,例如因爲它們不能用作模板的整型常量。

此外,只有類似這樣的事情會實際上給編譯時評價:

inline constexpr long long _xx(unsigned long long v) { 
    return (v > 100) ? throw std::exception() : v; 
} 
constexpr auto a= 150_xx; 

所以,這將不會編譯。但是,這會:

cout << 150_xx << endl; 

而下面是不允許的:

inline constexpr long long _xx(unsigned long long v) { 
    return some_trait<v>::value; 
} 

這很煩人,但是自然考慮到(其他)constexpr功能也可以在執行過程中被調用。

對於整數自定義文字只有可以強制編譯時處理,通過使用模板表單。在我的問題和自我回答的例子:https://stackoverflow.com/a/13869688/1149664