Reputation: 1027
I started experimenting with constexpr
.
What I'm trying to achieve is to validate literal
numeric values
provided as ctor parameters.
I started with the following, throwing if constructing MyStruct
with a value <= 4.
constexpr int validate(int v)
{
return (v > 4) ? v : throw exception();
};
struct MyStruct final
{
constexpr MyStruct(const int v)
: _v{validate(v)}
{
}
void add(int toAdd)
{
_v += toAdd;
}
int _v;
};
int main(int argc, char**)
{
constexpr MyStruct a{500}; // ok so far...
a.add(argc); // ...nope
MyStruct b{500}; // check at runtime :(
MyStruct c{argc}; // runtime check ok
}
Marking MyStruct
as constexpr
works as expected but this prevent calling add
since it is not mutable.
I think this could be done since I'm targeting only literal values (known at compile time).
I'd like to avoid templates.
Upvotes: 3
Views: 422
Reputation: 217970
Function arguments are not const expression :-/
You might pass std::integral_constant<std::size_t, 4u>
to allow the compile time check inside the constructor:
struct MyStruct final
{
// For runtime or constexpr usage.
constexpr MyStruct(int v) : _v{validate(v)} {}
// For compile-time values
template <std::size_t N>
constexpr MyStruct(std::integral_constant<std::size_t, N>) : _v{N}
{
static_assert(N > 4, "Unexpected");
}
// ...
};
and then
MyStruct b{std::integral_constant<std::size_t, 500>{}};
Upvotes: 5