es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La inclusión de condiciones a través de has-include-expression y has-attribute-expression se comporta de manera diferente.

#include <iostream>

#define Abc likely

#if __has_cpp_attribute(Abc)
#define Pn 0
#endif

#if __has_cpp_attribute(likely)
#ifndef Pn
#define Pn 1
#endif
#endif

int main(){
   std::cout << Pn;
}

En este ejemplo, GCC imprime 0 mientras que Clang imprime 1. Según [cpp.cond] p5:

Cada expresión __has_cpp_attribute se reemplaza por un número pp no nulo que coincida con la forma de un literal entero si la implementación admite un atributo con el nombre especificado interpretando los pp-tokens, después de la expansión de macros, como un token de atributo, y por 0 de lo contrario. El programa no es válido si los pp-tokens no coinciden con la forma de un token de atributo.

Entonces, la directiva #if __has_cpp_attribute(Abc) debería comportarse de la misma manera que #if __has_cpp_attribute(likely). GCC tiene el comportamiento correcto. De nuevo, considera este ejemplo:

#include <iostream>

#define Head <iostream>

#if __has_include(Head)
#define Pn 0
#endif

#ifndef Pn
#define Pn 1
#endif

int main(){
   std::cout << Pn;
}

En este ejemplo, ambos compiladores imprimen 0. Sin embargo, según [cpp.cond] p4:

El archivo de encabezado o fuente identificado por la secuencia de tokens de preprocesamiento entre paréntesis en cada expresión __has_include contenida se busca como si esa secuencia de tokens de preprocesamiento fuera los pp-tokens en una directiva #include, excepto que no se realiza una nueva expansión de macros. Si tal directiva no cumple los requisitos sintácticos de una directiva #include, el programa no es válido. La expresión __has_include se evalúa como 1 si la búsqueda del archivo fuente tiene éxito y como 0 si la búsqueda falla.

Ten en cuenta la redacción en negrita, lo que significa que Head no se reemplazará por <iostream>, ya que no hay tal archivo fuente. Por lo tanto, Pn debería ser 1 en su lugar. ¿Podría considerarse un error de GCC y Clang?

Tags:  ,

Answer

  1. Avatar for davy.ai

    El comportamiento de GCC y Clang en el primer ejemplo es inconsistente con el estándar. Según [cpp.cond] p5, la directiva __has_cpp_attribute debería comportarse de la misma manera después de la expansión de macros. Por lo tanto, la directiva # if __has_cpp_attribute(Abc) debería comportarse de la misma manera que #if __has_cpp_attribute(likely). Así, GCC tiene el comportamiento correcto en este caso.

    En el segundo ejemplo, ambos compiladores se comportan correctamente según el estándar. La búsqueda del archivo de encabezado se realiza como si fuera una directiva #include, pero no se realiza ninguna expansión adicional de macros. Por lo tanto, Head no se reemplazará por <iostream> y la expresión has-include se evalúa como 0 ya que no existe tal archivo de encabezado. En este caso, ambos compiladores evalúan correctamente Pn como 1.

    Por lo tanto, no se puede considerar un error de GCC ni de Clang en el segundo ejemplo.

Comments are closed.