簡體   English   中英

強制在編譯期間評估常量表達式?

[英]Forcing a constant expression to be evaluated during compile-time?

幾天前,我詢問編譯器決定是否在編譯期間計算constexpr函數。

什么時候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));
}

EDIT1:

使用這種方法的一個警告是, constexpr函數可以接受浮點並分配給constexpr浮點變量,但是不能將浮點類型用作非類型模板參數。 此外,對其他種類的文字也有同樣的限制。

你的lambda會為此工作,但我猜你需要一個默認捕獲來獲得有意義的錯誤消息,當非constexpr東西傳遞給函數時。 結束std::move是可有可無的。

EDIT2:

呃,你的lambda方法對我不起作用,我剛才意識到,它甚至可以工作,lambda不是constexpr函數。 它也不適合你。

似乎沒有辦法解決它,但在本地范圍內初始化constexpr變量。

EDIT3:

哦,好吧,我的壞,lambda的目的只是評價。 所以它正在努力。 相反,它的結果是無法跟隨另一個編譯時間eval。

EDIT4:

在C ++ 17上, lambdas現在可以在constexpr上下文中使用 ,因此刪除了EDIT2 / EDIT3中引用的限制! 所以lambda解決方案是正確的。 有關更多信息, 請參閱此評論

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM