niño - Incluir encabezados de C en un espacio de nombres de C++: ¿es un comportamiento estándar?
nombres con g (2)
Se ha creído que los archivos de encabezado C deben incluirse en el nivel superior del programa C ++. De todos modos, descubrí accidentalmente que C ++ está permitiendo la inclusión de encabezados de C en un espacio de nombres secundario.
namespace AAA {
extern "C" {
#include "sqlite3.h" // C API.
}
}
Y luego, todos los tipos C y funciones se colocarán en el espacio de nombres. ¡Más interesante aún, todas las funciones de C vinculadas también están funcionando! También descubrí que esto puede causar algún problema en el preprocesador, pero excepto que, parece estar funcionando bastante bien.
¿Es este un comportamiento estándar? (Estoy usando Clang 3.x) Si es así, ¿cuál es el nombre de esta función y dónde puedo encontrar esta característica mencionada en el estándar?
¿Es este un comportamiento estándar?
Sí, el estándar es compatible con el comportamiento, ya que el compilador de C ++ no tiene realmente la noción de que el código sea "C" en lugar de "C ++", excepto cuando se usa la extern "C"
para inhibir la manipulación del espacio de nombres.
La consecuencia de no inhibir la mutilación es que puede terminar con errores de "símbolo no resuelto" en el momento del enlace si trata de vincularse con una biblioteca de C que define los símbolos fuera de línea (variables extern
, funciones) mencionadas en el encabezado.
Si es [una característica estándar], ¿cuál es el nombre de esta característica y dónde puedo encontrar esta característica mencionada en la norma?
Esto es solo una consecuencia de la forma en que funciona #include
, que se define en 16.2 Inclusión del archivo fuente [cpp.include], fundamentalmente:
[un
#include
] provoca la sustitución de esa directiva por todo el contenido del archivo fuente identificado por la secuencia especificada entre los delimitadores ".
Por lo tanto, lo que ocurra con el encabezado "C" es exactamente como si las sentencias y llaves de namespace
/ extern
circundantes existieran en la parte superior e inferior del archivo de encabezado ... en el momento en que comience la siguiente fase de compilación, es irrelevante donde el el código fuente proviene de (excepto con el propósito de mostrar mensajes de error que se relacionan correctamente con el archivo fuente).
Incluso puedes hacer cosas extrañas como
//test.c
int
#include "main.h"
{
return 1;
}
//main.h
main(void)
Las macros del preprocesador se expanden antes de que se realice cualquier comprobación de sintaxis. El ejemplo anterior se expandirá a
int
main(void)
{
return 1;
}
Que es el código legal. Si bien debería evitar tales ejemplos, hay casos en los que incluir otro elemento es muy útil. En tu pregunta, depende de cómo se mancillan los nombres durante la compilación. Si todas las definiciones en su archivo de encabezado están declaradas con extern "C"
, los nombres se buscarán sin enredar en el archivo objeto, sin embargo, este no es el caso si el archivo objeto que contiene la implementación no usa el mismo espacio de nombres que el archivo. Definición en el código consumidor y no lo declara extern "C"
.