[英]Forcing a constant expression to be evaluated during compile-time?
幾天前,我詢問編譯器決定是否在編譯期間計算constexpr函數。
事實證明,只有在編譯時才會評估constexpr,如果所有參數都是常量表達式,並且您指定給它的變量也是常量表達式。
template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
return (expo != 0 )? base * POW(base, expo -1) : 1;
}
template<typename T>
void foobar(T val)
{
std::cout << val << std::endl;
}
int main(int argc, char** argv)
{
foobar(POW((unsigned long long)2, 63));
return 0;
}
如果我被告知是真的,這個代碼示例是非常不實際的,因為foobar不接受constexpr(由於某種原因你不能使用consexpr作為參數),POW在運行時被評估,即使它可能是可能的在編譯期間計算它。 強制編譯時評估的明顯解決方案是:
auto expr = POW((unsigned long long)2, 63);
foobar(expr);
然而,這迫使我使用額外的代碼行,每次我想確保在編譯時評估constexpr時都不需要這樣做。 為了使這更方便一點,我想出了以下可疑的宏:
#define FORCE_CT_EVAL(func) [](){constexpr auto ___expr = func; return std::move(___expr);}()
foobar(FORCE_CT_EVAL(POW((unsigned long long)2, 63)));
盡管它工作得很好,但我覺得好像有些不對勁。 創建匿名lambda會影響性能嗎? 通過rvalue引用返回實際上是將表達式移動到函數參數嗎? std :: move如何影響性能? 有沒有更好的單線解決方案呢?
只是不要把它埋在評論中:
#include <type_traits>
#define COMPILATION_EVAL(e) (std::integral_constant<decltype(e), e>::value)
constexpr int f(int i){return i;}
int main()
{
int x = COMPILATION_EVAL(f(0));
}
使用這種方法的一個警告是, constexpr
函數可以接受浮點並分配給constexpr
浮點變量,但是不能將浮點類型用作非類型模板參數。 此外,對其他種類的文字也有同樣的限制。
你的lambda會為此工作,但我猜你需要一個默認捕獲來獲得有意義的錯誤消息,當非constexpr
東西傳遞給函數時。 結束std::move
是可有可無的。
呃,你的lambda方法對我不起作用,我剛才意識到,它甚至可以工作,lambda不是constexpr
函數。 它也不適合你。
似乎沒有辦法解決它,但在本地范圍內初始化constexpr
變量。
哦,好吧,我的壞,lambda的目的只是評價。 所以它正在努力。 相反,它的結果是無法跟隨另一個編譯時間eval。
在C ++ 17上, lambdas現在可以在constexpr
上下文中使用 ,因此刪除了EDIT2 / EDIT3中引用的限制! 所以lambda解決方案是正確的。 有關更多信息, 請參閱此評論 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.