Recientemente encontré algo similar a las siguientes líneas:
#include <string>
// test if the extension is either .bar or .foo
bool test_extension(const std::string& ext) {
return ext == ".bar" || ".foo";
// it obviously should be
// return ext == ".bar" || ext == ".foo";
}
La función obviamente no hace lo que sugiere el comentario. Pero ese no es el punto aquí. Tenga en cuenta que esto no es un duplicado de ¿Puede usar 2 o más condiciones O en una declaración if? ¡ya que soy completamente consciente de cómo escribirías la función correctamente!
Empecé a preguntarme cómo un compilador podría tratar este fragmento. Mi primera intuición habría sido que esto se compilaría return true;básicamente. Al enchufar el ejemplo en godbolt , se demostró que ni GCC 9.2 ni clang 9 realizan esta optimización con optimización -O2.
Sin embargo, cambiando el código a 1
#include <string>
using namespace std::string_literals;
bool test_extension(const std::string& ext) {
return ext == ".bar"s || ".foo";
}
parece hacer el truco ya que el ensamblaje ahora es en esencia:
mov eax, 1
ret
Entonces, mi pregunta principal es: ¿Hay algo que me haya perdido y que no permita que un compilador realice la misma optimización en el primer fragmento?
1 Con ".foo"sesto ni siquiera se compilaría, ya que el compilador no quiere convertir un std::stringa bool;-)
Editar
El siguiente fragmento de código también se optimiza "correctamente" para return true;:
#include <string>
bool test_extension(const std::string& ext) {
return ".foo" || ext == ".bar";
}
operator==(string const&, string const&)es noexceptmientras operator==(string const&, char const*)que no es? No tengo tiempo para profundizar más ahora.
foo || ext == ".bar", la llamada se optimiza (ver edición). ¿Eso contradice tu teoría?
a || bsignifica "evaluar la expresión bsolo si la expresión aes false". Es ortogonal al tiempo de ejecución o al tiempo de compilación. true || foo()puede optimizarse true, incluso si foo()tiene efectos secundarios, porque (sin importar si está optimizado o no) el lado derecho nunca se evalúa. Pero foo() || trueno se puede optimizar a truemenos que el compilador pueda probar que las llamadas foo()no tienen efectos secundarios observables.
xor eax,eaxaunque sin esa opción llama a la función de comparación de cadenas. No tengo idea de qué hacer con eso.

string::compare(const char*)tiene algunos efectos secundarios que el compilador no eliminará (queoperator==(string, string)no tiene)? Parece poco probable, pero el compilador ya determinó que el resultado siempre es verdadero (también lo tienemov eax, 1ret) incluso para el primer fragmento.