[英]How to check a value and limits at compile time
I would like to create a settings class where a list of ID's has a default value and a limit to the value.我想创建一个设置类,其中 ID 列表具有默认值和值限制。 All using constexpr to allow for compile time checks.全部使用 constexpr 来允许编译时检查。
At compile time I would also like to validate the default values vs. the limits to ensure no illegal value is set.在编译时,我还想验证默认值与限制以确保没有设置非法值。 Here I hit a wall.我在这里撞墙了。
So, my base information is the following:所以,我的基本信息如下:
using item = std::variant<bool, int64_t, double, std::string_view>;
enum class ID {
fs,
fc,
fosc
};
struct ItemLimit
{
constexpr ItemLimit( item low, item high ) :
Low( low ),
High( high ){}
const item Low;
const item High;
};
struct item_entry{
ID id;
item default_value;
ItemLimit limit;
};
I would like to be able to write the list the following way:我希望能够按以下方式编写列表:
constexpr item_entry item_list[] = {
{ID::fs, 12.0, Limit( -12.0, 32.0 )},
{ID::fc, 1244, Limit( 4, 12333 )},
{ID::fc, false},
{ID::fc, 5'000'000'000, Limit( 1, 9999999999999999 )},
{ID::fosc, "HELLOOOOO"}
};
This requires a set of constructors, where I will limit to integer items for the following discussion.这需要一组构造函数,我将在下面的讨论中限制为整数项。
Both Limit and item_entry now looks like this: Limit 和 item_entry 现在看起来像这样:
template <typename T>
struct ValueLimit
{
constexpr ValueLimit( T low, T high ) :
low( low ),
high( high )
{
};
const T low;
const T high;
};
constexpr ValueLimit<int64_t> Limit( long long x, long long y ){
return ValueLimit<int64_t>( x, y );
}
struct item_entry{
constexpr item_entry( ID id, long long value, ValueLimit<int64_t> limit ) :
id( id ),
default_value( int64_t( value ) ),
limit( limit.low, limit.high )
{}
ID id;
item default_value;
};
Inside the item_entry constructor I would like to do a check for whether the value is inside the limits, but I can't figure out how.在 item_entry 构造函数中,我想检查该值是否在限制范围内,但我不知道如何进行。 All my efforts end up in expressions that "are not evaluated to a constant".我所有的努力都以“未评估为常数”的表达式结束。
The solution should ideally also work for floating point values.理想情况下,该解决方案也适用于浮点值。
Thanks in advance!提前致谢!
Henrik Andresen亨利克·安德森
The problem is that value
is not a constant expression in this context, as function arguments are never constant expressions :问题是value
在这种情况下不是常量表达式,因为函数参数永远不是常量表达式:
constexpr item_entry( ID id, long long value, ValueLimit<int64_t> limit )
^~~~~~~~~~~~~~~
You need to pass value
in such a way that it can be used as part of a constant expression : std::integral_constant
is exactly what you need.您需要以一种可以将其用作常量表达式的一部分的方式传递value
: std::integral_constant
正是您所需要的。
template <long long X> // <==
constexpr item_entry( ID id,
std::integral_constant<long long,X> value, // <==
ValueLimit<int64_t> limit )
{
static_assert(value >= limit.low && value <= limit.high); // <==
}
The same principle applies to limit
:同样的原则适用于limit
:
template <typename T, T Low, T High>
struct ValueLimit
{
static constexpr T low = Low;
static constexpr T high = High;
};
Final changes:最终变化:
struct item_entry
{
template <long long X, typename Limit>
constexpr item_entry( ID id, std::integral_constant<long long, X> value, Limit ) :
id( id ),
default_value( int64_t( value ) )
{
static_assert(value >= Limit::low && value <= Limit::high);
}
ID id;
item default_value;
};
Usage example:用法示例:
template <long long X>
constexpr std::integral_constant<long long, X> ic{};
template <int64_t Low, int64_t High>
constexpr ValueLimit<int64_t, Low, High> limit{};
constexpr item_entry item_list[] = {
{ID::fc, ic<1244>, limit< 4, 12333 >},
{ID::fc, ic<5'000'000'000>, limit< 1, 9999999999999999 >}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.