c++ - para - ¿Hay una manera de insertar un nombre global en un espacio de nombres y hacer que esté disponible solo desde ese espacio de nombres?
para que sirve el using namespace std en dev c++ (4)
Digamos que tengo una función con el enlace "C"
en el ámbito global.
extern "C" int fun(int);
Luego, si quiero hacerlo visible en un espacio de nombres, lo haría:
namespace foo {
using ::fun;
}
Pero después de esto todavía puedo llamarlo como ::fun(0)
además de foo::fun(0)
.
Así que mi pregunta es, ¿hay una manera de no permitir la llamada desde el espacio de nombres global para la fun
función y solo permitir que se llame desde el namespace foo
de namespace foo
?
Como el lenguaje C no tiene espacios de nombres, parte del especificador extern "C"
indica que el nombre de la fuente no tiene espacio de nombres.
Por lo tanto, el siguiente código invocaría la función C
foo
:
namespace bar
{
extern "C" void foo();
}
void foo() {} // note: legal, so no pre-existing ::foo()
void caller() {
bar::foo(); // calls the C function
}
Así que podrías hacer
namespace bar
{
extern "C"
{
#include "foo.h"
}
}
o si necesitas compartirlo con el código C:
#ifdef __cplusplus
namespace bar
{
extern "C"
{
#endif
// .. C-compatible definitions etc
#ifdef __cplusplus
}
}
#endif
El estándar establece claramente que la función C externa se declara dentro de un espacio de nombres, incluso si C no conoce los espacios de nombres:
7.5 / 4: Una especificación de enlace no establece un alcance. Una especificación de vinculación solo se producirá en el ámbito del espacio de nombres.
Entonces, en lugar de declarar la función en el espacio de nombres global, podría definirla directamente en su foo namespace
:
// no declaration in global namespace, but...
namespace foo {
extern "C" int fun();
}
Entonces podría referirse a esta función solo a través del espacio de nombres:
foo::fun(); // yes !
::fun(); // doesn''t compile !!!
Tenga en cuenta que incluso podría declarar la función C externa en varios espacios de nombres. Todos se referirían a la misma función C:
namespace bar {
extern "C" int fun();
}
...
foo::fun(); // ok
bar::fun(); // ok - same result as foo::fun();
Esto está garantizado por la norma:
7.5 / 6: Como máximo, una función con un nombre particular puede tener un enlace en lenguaje C. Dos declaraciones para una función con enlace en lenguaje C con el mismo nombre de función (ignorando los nombres de espacio de nombres que lo califican) que aparecen en diferentes ámbitos de espacio de nombres se refieren a la misma función.
Tenga en cuenta que si la función externa se declaró en el espacio de nombres global en una unidad de compilación debido a algunas restricciones específicas, aún podría organizar que esta declaración no se vea en las otras unidades de compilación en las que usaría su espacio de nombres local. Esto es perfectamente válido de acuerdo con la declaración estándar anterior. Sin embargo, sería necesario tener cuidado si juegas con diferente visibilidad en diferentes unidades de compilación.
No puede evitar el uso (mal) intencional explícito aquí, pero puede ocultarlo en un archivo de implementación separado para que sea difícil de usar accidentalmente:
En su encabezado, declare el envoltorio:
namespace foo
{
int fun(int);
}
Luego, en un único archivo fuente privado, lo envuelves:
extern "C" int fun(int);
namespace foo
{
int fun(int v) { return ::fun(v); }
}
Puede hacer esto desde C ++ 11 utilizando una declaración deleted de una función ambigua en un espacio de nombres en línea anonymous :
inline namespace { int fun(int) = delete; }
Intentar llamar a ::fun(0)
o fun(0)
dará un error:
error: call of overloaded ''fun(int)'' is ambiguous
note: candidate: int fun(int)
extern "C" int fun(int);
^~~
note: candidate: int {anonymous}::fun(int) <deleted>
inline namespace { int fun(int) = delete; }
^~~
Example .