"constexpr if" vs " if " con optimizaciones - ¿por qué se necesita "constexpr"?


C++1z introducirá "constexpr if" - un if que tendrá una de las ramas eliminadas, basado en la condición. Parece razonable y útil.

Sin embargo, ¿no es posible prescindir de la palabra clave constexpr? Creo que durante la compilación, compilador debe saber wheter condición se conoce durante el tiempo de compilación o no. Si lo es, incluso el nivel de optimización más básico debe eliminar la rama innecesaria.

Por ejemplo (ver en 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 muestra, que incluso gcc-4.4.7 con-O0 no compiló "return 1", por lo que logró lo prometido con constexpr if. Obviamente, este compilador antiguo no será capaz de hacerlo cuando la condición es el resultado de la función constexpr, pero el hecho sigue siendo: el compilador moderno sabe si la condición es constexpr o no y no necesita que lo diga explícitamente.

Así que la pregunta es:

¿Por qué se necesita" constexpr " en " constexpr si"?

Author: ildjarn, 2016-12-05

1 answers

Esto es fácil de explicar a través de un ejemplo. Considere

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

Y

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

Invocando

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

Desencadenará un error de compilación(ejemplo de wandbox), porque ambas ramas de la instrucción if tienen que estar bien formadas.

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{});
    ^

Cambiando pet a usar 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(); }
}

Solo requiere que las ramas sean analizables, solo la rama que coincida con la condición debe estar bien formada (ejemplo de wandbox).

El fragmento

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

Compilará y funcionará como se espera.

 44
Author: Vittorio Romeo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-16 07:20:30