![](/img/trans.png)
[英]Using a runtime parameter (variable) in C++ metaprogramming at compile-time
[英]C++ - Can I create compile-time variable object?
我最近在使用constexpr,但我只是意識到我用錯了。 我很好奇我是否可以創建一個編譯時變量(或變量對象)。
來自cppreference.com的constexpr定義告訴我們:
constexpr說明符聲明可以在編譯時評估函數或變量的值。
那么為什么下面的代碼不正確?
#include <iostream>
int main()
{
constexpr int x = 30;
x += 10;
std::cout << x;
}
該整數可以在編譯時完美評估。 我知道編譯器可以在沒有constexpr修飾符的情況下優化此類變量,但是如果我想擁有一個編譯時對象怎么辦?
#include <iostream>
class ctFoo {
public:
ctFoo()
: value{ 0 }
{
}
int accumulate(int value_) {
return (value += value_), value;
}
int value;
};
int main()
{
ctFoo foo;
std::cout << foo.accumulate(100);
}
我有什么把握可以在編譯時評估此代碼? 我之所以這么問,是因為我目前正在編寫一些Vector2和Vector3數學,並且我想創建這樣的實現,它將能夠處理編譯時和運行時計算。 可能嗎
謝謝。
正如max66所指出的,constexpr隱含const,但是我在問:為什么這樣? 現代編譯器應該能夠在編譯時推斷出它的價值。 另外,我知道我可以簡單地創建另一個constexpr常量(廣告最上面的代碼示例),但是我的問題是針對更復雜的代碼。
那么為什么下面的代碼不正確?
#include <iostream> int main() { constexpr int x = 30; x += 10; std::cout << x; }
constexpr
暗示const
。 您需要將此約束到constexpr
上下文中:
constexpr int foo() {
int x = 30;
x += 10;
return x;
}
但是,如果我想擁有一個編譯時對象怎么辦?
#include <iostream> class ctFoo { public: ctFoo() : value{ 0 } { } int accumulate(int value_) { return (value += value_), value; } int value; };
給它constexpr
支持:
constexpr ctFoo() : value{ 0 }
constexpr int accumulate(int value_) {
value += value_;
return value;
}
現在的保證是,如果您的ctFoo
對象是一個常量表達式,並且您在constexpr
上下文(如foo
函數示例)中調用accumulate
,那么您可以在編譯時使用結果。 例如:
constexpr int foo() {
ctFoo f;
f.accumulate(10);
return f.value;
}
static_assert(foo() == 10);
要么:
constexpr void accumulate(ctFoo& f) {
f.accumulate(10);
}
constexpr int foo() {
ctFoo f;
accumulate(f);
return f.value;
}
static_assert(foo() == 10);
這里要記住的關鍵是,運行時評估也是一種選擇。 如果我將ctFoo
的value
設置為運行時值(例如,用戶輸入),那么在編譯時就不可能發生accumulate
調用。 但這沒關系-相同的代碼在兩種情況下均有效。
您需要繼續閱讀:
對象聲明中使用的
constexpr
說明符暗含const
。
您不能更改constexpr
,這就是您可以在常量表達式中使用它的全部目的。
接下來要考慮的是,您似乎正在混合兩種不同的上下文。 我毫不懷疑,編譯器將能夠完全優化您的最后一個示例,但這就是constexpr
所做的其他事情。 關鍵字表示它的含義可以在編譯時進行評估,但不一定必須如此。 因此,您可以編寫一個constexpr
函數,其中的所有內容都可以在編譯時進行評估,並且仍然可以在運行時運行。
真正只有在編譯時就可以評估的對象(因此沒有優化程序),並且您可以修改的唯一時間是在編譯時上下文中。 您處於這樣的上下文中,例如constexpr
函數中:
constexpr int foo() {
int a = 10;
++a; // I can modify a.
return a;
// even if I did this: int Array[foo()];
}
但是您在常規功能中沒有這種能力,而該語言只是不允許這樣做。
因此,回答您的問題:
我有什么把握可以在編譯時評估此代碼?
您沒有任何東西,因為您沒有使用constexpr
。 即使這樣,如果您在不需要編譯時求值的地方調用constexpr
函數,則該函數可能會在運行時被調用,
可能嗎
可以肯定的是,您已經創建了constexpr
函數,如果需要,它將在編譯時進行評估。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.