3 votes

Utilisation de constexpr pour valider les paramètres littéraux dans un constructeur

J'ai commencé à expérimenter avec constexpr .
Ce que j'essaie de faire, c'est de valider literal valeurs numériques fournies en tant que paramètres du CTOR.
J'ai commencé par ce qui suit, en lançant si l'on construit MyStruct avec une valeur <= 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
}

Marquage MyStruct comme constexpr fonctionne comme prévu, mais cela empêche d'appeler add puisqu'il n'est pas mutable.

Je pense que c'est possible puisque je ne vise que les valeurs littérales (connues au moment de la compilation).
J'aimerais éviter les modèles.

5voto

Jarod42 Points 15729

Les arguments des fonctions ne sont pas des expressions constantes :-/

Vous pouvez passer std::integral_constant<std::size_t, 4u> pour permettre la vérification au moment de la compilation à l'intérieur du constructeur :

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");
    }

    // ...
};

et ensuite

MyStruct b{std::integral_constant<std::size_t, 500>{}};

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X