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.

¿Hay alguna manera de definir una plantilla de función en un encabezado y hacerla inaccesible a los archivos que incluyen el encabezado?

Tengo una plantilla de clase que se ve así:

foo.h

template<class C>
class Foo
{
public:
    void memberFunc();
};

Incluye “foo.tpp”

foo.tpp

“`
void Foo::memberFunc()
{

}

Ignora el archivo .tpp, es solo algo que hago para dar la ilusión de separar la declaración y la implementación, obviamente eso no es (exactamente) posible con las plantillas.

Mi archivo de implementación es mucho más largo en realidad, y dentro de él tengo algunas plantillas de funciones auxiliares de ámbito global que utilizan las funciones miembro, funciones que no tienen sentido como funciones miembro y que no quiero que los usuarios de la clase tengan nada que ver.

template int helper1() { … }

template void helper2() { … }

template
void Foo::memberFunc()
{

helper1();

helper2();

}

Esto lo hago todo el tiempo en archivos de implementación .cpp y olvidé que cuando lo hago en esta versión ficticia de un archivo .cpp, la declaración e implementación de estas pequeñas funciones auxiliares en realidad terminan en el archivo de encabezado de la plantilla de clase. Esto lleva a que los usuarios del archivo de encabezado de la plantilla de clase tengan sus espacios de nombres llenos de funciones auxiliares que son inútiles fuera de las implementaciones de las funciones miembro.

Obviamente, podría simplemente ponerlas en un espacio de nombres:

namespace foo_helpers
{

template void helper1() {…}

template int helper2() {…}

}

Pero aún así, esto lleva a que el código externo pueda utilizar estas funciones. Solo importan para la implementación de las funciones miembro y quiero que se refleje.

Al buscar una solución, aprendí sobre el concepto de espacios de nombres sin nombre. Según entiendo, solo permiten que la unidad de traducción actual acceda a su contenido. Eso suena exactamente a lo que necesito, así que cambié las funciones auxiliares a esto:

namespace
{

template void helper1() {…}

template void helper2() {…}

}

Pero no funciona, las funciones todavía se pueden utilizar en los archivos que incluyen el encabezado.

¿Hay alguna manera de ocultar estas funciones auxiliares del código externo?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Sí, hay una manera de ocultar las funciones auxiliares del código externo utilizando espacios de nombres sin nombre. El problema con la implementación actual es que el espacio de nombres sin nombre está en el archivo de encabezado, lo que lo hace accesible para cualquier unidad de traducción que incluya el encabezado. Para solucionar esto, puede mover el espacio de nombres sin nombre al archivo “.tpp”, que no es incluido por el código externo.

    Aquí hay una implementación actualizada:

    foo.h

    template<class c="">
    class Foo
    {
    public:
        void memberFunc();
    };
    
    #include "foo.tpp"
    

    foo.tpp

    namespace
    {
        template<class c="">
        void helper1() {...}
    
        template<class c="">
        int helper2() {...}
    }
    
    template<class c="">
    void Foo<c>::memberFunc()
    {
        ...
        helper1<float>();
        ...
        helper2<c>();
        ...
    }
    

    Al mover el espacio de nombres sin nombre al archivo “.tpp”, las funciones auxiliares solo son accesibles dentro de la unidad de traducción donde se incluye el archivo “.tpp” (es decir, dentro del mismo archivo que la definición de la plantilla de clase). El código externo que incluye el archivo de encabezado no tendrá acceso a las funciones auxiliares.

    ¡Espero haber sido de ayuda! Háganme saber si tienen alguna pregunta adicional.

Comments are closed.