我有幾個問題!我對模板和 constexpr 以及它們的區別感到困惑。
我知道模板是在編譯時實體化的,它們是在編譯時執行還是僅在運行時執行?有沒有我可以一起使用它們來獲得一些好處的例子?
如果我們有一個像這個例子中那樣帶有 constexpr 的模板會發生什么。
template <typename T>
constexpr T get_sum(T a, T b)
{
return a b;
}
int main()
{
constexpr int a = get_sum(2,3); // compile time?
const float b = get_sum(2.2,3.2); // compile time?
float c = get_sum(2.2,3.2); // run time?
}
uj5u.com熱心網友回復:
你get_sum是一個函式模板。get_sum<int>是一個幾乎和任何其他函式一樣的函式。不要被模板引數推導弄糊涂了,這確實發生在編譯時。如果不扣除,您的main情況與以下完全相同:
constexpr int a=get_sum<int>(2,3);
const float b=get_sum<double>(2.2,3.2);
float c=get_sum<double>(2.2,3.2);
簡而言之,模板在需要時由編譯器實體化。一旦編譯器合成了一個函式,例如get_sum<int>這是一個與其他函式一樣的函式,并且該函式constexpr是否與它是否是實體化模板的結果是正交的。
constexpr在函式上告訴編譯器該函式可以在編譯時被評估。當在 constexpr 背景關系中呼叫時,編譯器必須在編譯時對其進行評估。例如constexpr int a在編譯時初始化。Aconst float可能已經被編譯器初始化。甚至(非常量)float也可能被編譯器完全優化掉。只要程式的可觀察行為相同(實際上沒有使用您的 3 個變數),就沒有什么可以阻止編譯器優化某些內容。
Ergo:
int main()
{
constexpr int a=get_sum(2,3); // get_sum<int> must be called at compile time
const float b=get_sum(2.2,3.2); // get_sum<double> is likely to be called at compile time
float c=get_sum(2.2,3.2); // get_sum<double> might be called at compile time or runtime
// or not at all, because the call does not
// contribute to observable behavior
}
TL; 博士
函式是否是函式模板的實體化,函式是否constexpr正交。
uj5u.com熱心網友回復:
對于 constexpr,還有 static_assert。constexpr 可以在編譯時和運行時使用。(C 20 有 consteval,它只允許編譯時求值)。
#include <cassert>
template<typename type_t>
constexpr auto sum(const type_t& value1, const type_t& value2)
{
return value1 value2;
}
int main()
{
constexpr auto constexpr_value = sum(1, 2); // <== compile time
static_assert(constexpr_value == 3); // <== compile time validation
// or shorter
static_assert(sum(1, 2) == 3); // <== compile time evaluation
// constexpr's also can compile to runtime versions
auto value = sum(2, 3); // <== runtime evaluation
assert(value == 5);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/385154.html
上一篇:不同的模板簽名
