40 votes

"constexpr if" vs "if" avec optimisations - pourquoi "constexpr" est-il nécessaire?

C++1z présentera "constexpr si" - si un qui sera l'une des branches supprimées, en fonction de l'état. Semble raisonnable et utile.

Cependant, il n'est pas possible de le faire sans constexpr mot-clé? Je pense que lors de la compilation, le compilateur doit savoir si la condition est connue lors de la compilation du temps ou pas. Si elle l'est, même le plus basique niveau d'optimisation devrait supprimer les branche.

Par exemple (voir dans godbolt: https://godbolt.org/g/IpY5y5):

int test() {
    const bool condition = true;
    if (condition) {
      return 0;
    } else {
      // optimized out even without "constexpr if"
      return 1;
    }
}

Godbolt explorer montre, que même gcc-4.4.7 avec -O0 n'a pas compiler "return 1", de sorte qu'il atteint ce qui était promis avec constexpr si. Manifestement, l'ancien compilateur ne sera pas en mesure de le faire lorsque la condition est le résultat de la constexpr fonction, mais le fait demeure: moderne compilateur sait si la condition est constexpr ou pas et n'a pas besoin de moi pour le dire explicitement.

La question est donc:

Pourquoi "constexpr" nécessaire "constexpr si"?

54voto

Vittorio Romeo Points 2559

C'est facile à expliquer par un exemple. Envisager

struct Cat { void meow() { } };
struct Dog { void bark() { } };

et

template <typename T>
void pet(T x)
{
    if(std::is_same<T, Cat>{}){ x.meow(); }
    else if(std::is_same<T, Dog>{}){ x.bark(); }
}

Invoquant

pet(Cat{});
pet(Dog{});

va déclencher une erreur de compilation (wandbox exemple), parce que les deux branches de l' if doivent être bien formés.

prog.cc:10:40: error: no member named 'bark' in 'Cat'
    else if(std::is_same<T, Dog>{}){ x.bark(); }
                                     ~ ^
prog.cc:15:5: note: in instantiation of function template specialization 'pet<Cat>' requested here
    pet(Cat{});
    ^
prog.cc:9:35: error: no member named 'meow' in 'Dog'
    if(std::is_same<T, Cat>{}){ x.meow(); }
                                ~ ^
prog.cc:16:5: note: in instantiation of function template specialization 'pet<Dog>' requested here
    pet(Dog{});
    ^

Évolution pet utilisation if constexpr

template <typename T>
void pet(T x)
{
    if constexpr(std::is_same<T, Cat>{}){ x.meow(); }
    else if constexpr(std::is_same<T, Dog>{}){ x.bark(); }
}

ne nécessite que les branches de l'parseable seule la branche qui correspond à la condition doit être bien formé (wandbox exemple).

L'extrait de code

pet(Cat{});
pet(Dog{});

compiler et fonctionner comme prévu.

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