[英]What is the best way in C++ to have a compile-time constant depend on a type's size?
[英]Best way of defining a compile-time constant
在C ++ 11中定義簡單常量值的最佳方法是什么,這樣就沒有運行時懲罰? 例如:(不是有效代碼)
// Not ideal, no type, easy to put in wrong spot and get weird errors
#define VALUE 123
// Ok, but integers only, and is it int, long, uint64_t or what?
enum {
Value = 123
};
// Could be perfect, but does the variable take up memory at runtime?
constexpr unsigned int Value = 123;
class MyClass {
// What about a constant that is only used within a class, so
// as not to pollute the parent namespace? Does this take up
// memory every time the class is instantiated? Does 'static'
// change anything?
constexpr unsigned int Value = 123;
// What about a non-integer constant?
constexpr const char* purpose = "example";
std::string x;
std::string metadata() { return this->x + (";purpose=" purpose); }
// Here, the compiled code should only have one string
// ";purpose=example" in it, and "example" on its own should not
// be needed.
};
因為我被告知這是一個無用的問題,因為它背后沒有背景,這是背景。
我正在定義一些標志,以便我可以這樣做:
if (value & Opaque) { /* do something */ }
Opaque
的值在運行時不會改變,因為只有在編譯時才需要它才能讓它在我的編譯代碼中結束。 這些值也用在一個循環中,該循環對圖像中的每個像素運行多次,所以我想避免運行時查找會降低它的速度(例如,內存訪問以在運行時檢索常量的值。)這不是'過早優化,因為算法目前需要大約一秒鍾來處理圖像,我經常有超過100個圖像要處理,所以我希望它盡可能快。
既然人們說這是微不足道的而且不用擔心它,我猜測#define
就像你可以達到字面值一樣接近,所以也許這是避免“過度思考”問題的最佳選擇? 我想普遍的共識是你只希望沒有人需要使用Opaque
這個詞或你想要使用的其他常量?
實際上,這比它看起來更棘手。
只是明確重申要求:
在C ++中,表達式可以是lvalues或prvalues(在C ++ 11和C之前, rvalues對應於相關概念)。 左值參考對象,因此它們可以在一個賦值表達式為L EFT-手側出現。 對象存儲和左值是我們想要避免的。
你想要的是一個標識符或id-expression來評估prvalue。
目前,只有普查員才能做到這一點,但正如您所觀察到的那樣,他們會留下一些需要的東西。 每個枚舉聲明都引入了一個新的,不同的類型,因此enum { Value = 123 };
引入一個不是整數的常量,但它自己的唯一類型轉換為int
。 這不是適合這項工作的合適工具,盡管它適用於工作。
你可以使用#define
,但這是一個黑客,因為它完全避免了解析器。 您必須使用所有大寫字母命名,然后確保相同的全大寫字母名稱不用於程序中的任何其他內容。 對於庫接口,這種保證尤其繁重。
下一個最佳選擇是函數調用:
constexpr int value() { return 123; }
但是,小心,因為constexpr
函數仍然可以在運行時進行評估。 你需要跳過一個箍來表達這個值作為計算:
constexpr int value() {
/* Computations that do not initialize constexpr variables
(or otherwise appear in a constant expression context)
are not guaranteed to happen at compile time, even
inside a constexpr function. */
/* It's OK to initialize a local variable because the
storage is only temporary. There's no more overhead
here than simply writing the number or using #define. */
constexpr int ret = 120 + 3;
return ret;
}
現在,您不能將常量稱為名稱,它必須是value()
。 函數調用運算符可能看起來效率較低,但它是完全消除存儲開銷的唯一當前方法。
你不能錯:
static constexpr const unsigned int Value = 123;
但老實說,盡量不要關心這一點。 喜歡,真的試試。
我認為您應該考慮C ++ 11為枚舉指定基礎類型的功能 ,適用於您的示例將是:
enum : unsigned int { Value = 123 };
這消除了您對使用枚舉的兩個異議之一,即您無法控制實際用於表示它們的類型。 但它仍然不允許非整數常量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.