Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using constexpr to validate literal parameters in constructor

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.

like image 953
Stefano Azzalini Avatar asked May 07 '26 22:05

Stefano Azzalini


1 Answers

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>{}};
like image 171
Jarod42 Avatar answered May 10 '26 13:05

Jarod42



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!