原問題
我想使用靜態成員變量爲了通過類型模板參數傳遞信息到模板類。這些變量不應該被包含在所有翻譯單元中的頭文件中設置,以便我可以在不重新編譯大部分目標文件的情況下更改它們。此外,對於不需要額外空間的變量,有一個方便的別名會很好。我認爲constexpr
只讀樣哪些值可以分配給`constexpr`參考?
static constexpr const int& alias = T::static_variable_name;
引用可以作爲這樣的別名,但不知道這是有效的。對於constexpr
reads
- 構造參數或將被分配必須只包含文字值,constexpr變量和函數值的一個限制。
所以,我想它使用g++ -std=c++11
並得到一種不一致的行爲對我的口味。代碼包含在這個問題的最後。在大多數的情況下,代碼編譯並運行正常,而是直接在非專業類模板使用h2g2_oracle::answer
時(見註釋「錯誤,爲什麼?」),編譯失敗與消息
src/main.cpp:18:57: error: the value of ‘h2g2_oracle::_answer’ is not usable in a constant expression static constexpr const int& answer = h2g2_oracle::answer; // ERROR; WHY? src/main.cpp:11:9: note: ‘int h2g2_oracle::_answer’ is not const int h2g2_oracle::_answer = 42;
爲什麼大多數constexpr
引用都是作爲別名工作的,而這個單獨的引用不是?
#include <iostream>
// a specific kind of oracle
class h2g2_oracle {
protected:
static int _answer;
public:
static constexpr const int& answer = _answer; // public alias for reading
};
int h2g2_oracle::_answer = 42;
// some class template using a specific kind of oracle
template<typename oracle>
struct forecast {
// try to define an own alias
static constexpr const int& answer = oracle::answer; // works
//static constexpr const int& answer = h2g2_oracle::answer; // ERROR; WHY?
};
// specialized version for the h2g2_oracle
template<>
struct forecast<h2g2_oracle> {
// also define the own alias
static constexpr const int& answer = h2g2_oracle::answer; // works
};
int main() {
static constexpr const int& answer = h2g2_oracle::answer; // works
std::cout << answer << std::endl;
std::cout << forecast<h2g2_oracle>::answer << std::endl;
return 0;
}
尋址
@Ben福格特有關the gain of constexpr
評論:是的,DYP is right with the assumption我喜歡的constexpr
版本其體內的初始化。 長評論:我非常肯定,在單獨的翻譯單元中進行初始化會強制程序使用存儲原始值地址的某個內存位置。因此,我認爲constexpr
可能對有用,總是在標題中(即模板(forecast<...>::answer
)和非模板(h2g2_oracle::answer
))具有靜態成員初始化。我知道我可以將非模板類更改爲包含一個虛擬模板參數,以便在頭中也可以完成初始化,但仍然最初對我來說,解決方案constexpr
更容易。
@dyp關於possible g++ bug:啊,我沒想到找到一個這樣的「簡單」測試。現在我看到了相關的問題,這對我來說似乎是一個很好的解釋。任何可行的方法來確認/報告/幫助?如果你對此相當有信心,我至少可以接受這個答案。
關於definition before using @dyp:是的,我檢查了G ++是好的,在即使h2g2_oracle
定義來的forecast
定義後的非專業forecast
使用oracle::answer
。但是,當在main
中使用forecast<h2g2_oracle>::answer
時,h2g2_oracle
必須是完成。這對我來說看起來很合理。其他想法:我更加着迷的是如何將靜態成員初始化爲另一個靜態成員(可能位於不同的翻譯單元)的引用方式。
關於
有趣@dyp,我不知道,如果你需要H2G2定義::答案預測使用它之前;它應該是odr-used(我覺得很奇怪)。
我想我現在明白了你的觀點。這也是我覺得有趣的地方:事實上,int h2g2_oracle::_answer = 42;
甚至可以被移到不同的翻譯單位,它仍然有效。不知何故,鏈接器(即時簡單字)設法在需要的地方「插入」正確的內存地址h2g2_oracle::_answer
。
目前還不清楚你認爲'constexpr'在這裏爲你做了什麼,但我寧願懷疑它不會以任何方式幫助你。 – 2014-09-30 13:32:57
@BenVoigt'constexpr'允許在類體中定義。 – dyp 2014-09-30 13:48:23
[鏗鏘++ 3.5不抱怨](http://coliru.stacked-crooked.com/a/34212c61d558c7a5) – dyp 2014-09-30 13:50:45