![](/img/trans.png)
[英]constexpr constructor gives a different result when evaluated at compile time by GCC
[英]Constexpr constructor is not evaluated at compile time
我想在編譯時引入帶有錯誤檢查的強類型。 對於我的 chrono 類型,我注意到當底層類型從int64_t
更改為int32_t
時,字面量會悄無聲息地變窄,從而導致溢出。 所以我引入了一個顯式檢查。
但是,即使對於無法表示的常量參數(如delay_t {10s}
,編譯時也不會檢查此檢查。
#include <chrono>
#include <cstdint>
#include <stdexcept>
struct delay_t {
std::chrono::duration<int32_t, std::nano> value {};
constexpr explicit delay_t(std::chrono::duration<int64_t, std::nano> delay)
: value {delay}
{
if (value != delay) {
throw std::runtime_error("delay cannot be represented.");
}
};
};
auto foo(delay_t delay) -> void {}
auto main() -> int {
using namespace std::chrono_literals;
foo(delay_t {10s}); // here I want a compile time error,
// but I get a runtime error.
return 0;
}
不幸的是,這會編譯並導致運行時錯誤。 我驗證了文字operator"" s
是一個constexpr
並且它在delay_t
構造函數中使用consteval
工作。 我還想使用具有運行時值的類型,所以這不是一個選項。
我如何告訴上面的編譯器在編譯時評估像time_t {10s}
這樣的常量文字? 我正在使用 C++20。
constexpr
僅在編譯時以常量表達式求值,不依賴於參數。
你可以將你的表達拆分為
constexpr delay_t delay{10s}; // Compile time evaluated, so error at compile time
foo(delay);
通過consteval
function 傳遞它。
template<typename T>
consteval T force_constexpr(const T& value) noexcept
{
return value;
}
你可以像這樣使用它:
foo(force_constexpr(delay_t {0s})); // No compile-time error
foo(force_constexpr(delay_t {10s})); // Compile-time error
要在編譯時強制檢查,chrono 類型的構造需要是consteval 。 沒有其他辦法了。
consteval explicit delay_t(duration<int64_t, std::nano> delay)
: delay_t {wrapped_{delay}} {};
為了也允許運行時構造,我們需要另一種構造delay_t
的方法。 例如,我們可以使用static 方法,即 constexpr 。
constexpr static auto runtime(duration<int64_t, std::nano> delay) -> delay_t {
return delay_t {wrapped_ {delay}};
}
由於此方法需要以某種不同的方式構造delay_
,因此我們需要第二個非 consteval 構造函數。 但是由於我們已經有一個用於 chrono 的,我們需要引入一個私有包裝器類型:
private:
struct wrapped_ {
duration<int64_t, std::nano> value;
};
constexpr delay_t(wrapped_ delay) : value {delay.value} {
if (value != delay.value) {
throw std::runtime_error("delay cannot be represented.");
}
};
使用delay_t
現在默認強制執行編譯時檢查:
foo(delay_t {1s});
foo(delay_t {10s}); // gives compile time error
foo(delay_t::runtime(10s)); // gives a runtime error
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.