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.

¿Existe alguna forma de contar la cantidad de veces que se ha llamado a una función constexpr?

Tengo una plantilla de clase y una plantilla de función que se ven así:

template<typename t="">
struct IdGenerator
{
    static unsigned int s_idCount_;
    template<typename u="">
    static int newID()
    {
        static const unsigned int id = s_idCount_++;
        return id;
    };
};
template<typename t=""> unsigned int IdGenerator<t>::s_idCount_ = 1;

Como puedes ver, me permite obtener un ID para cada combinación de dos tipos:

IdGenerator<int>::newID<float>() // 1
IdGenerator<int>::newID<char>() // 2
IdGenerator<float>::newID<int>() // 1
...

Lo que estoy intentando hacer, pero no puedo entender completamente, es hacer que todo esto funcione en tiempo de compilación. Me parece que todo esto podría evaluarse en tiempo de compilación ya que todo lo que estamos haciendo es contar las instancias de plantillas, lo cual es un evento en tiempo de compilación.

Pero al mismo tiempo, no tengo ni idea de cómo se incrementaría el contador de ID en tiempo de compilación.

¿Es posible lo que estoy intentando hacer, si no con este diseño específico, entonces con algún otro diseño?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible hacer que todo esto funcione en tiempo de compilación. Una manera de lograr esto es utilizando funciones y variables constexpr.

    En primer lugar, hagamos la variable s_idCount_ constexpr:

    template<typename t="">
    struct IdGenerator
    {
        static constexpr unsigned int s_idCount_ = 1;
    
        template<typename u="">
        static constexpr int newID()
        {
            static const unsigned int id = s_idCount_++;
            return id;
        };
    };
    

    Ahora, la variable s_idCount_ puede evaluarse en tiempo de compilación. Sin embargo, dado que newID() modifica s_idCount_, usarlo causará un error de compilación. Para solucionar esto, podemos utilizar una función constexpr recursiva para incrementar el contador de id en tiempo de compilación. Aquí tienes un ejemplo de cómo se puede hacer esto:

    template<unsigned int="" n="">
    constexpr unsigned int increment()
    {
        return N + 1;
    }
    
    template<typename t="">
    struct IdGenerator
    {
        static constexpr unsigned int s_idCount_ = 1;
    
        template<typename u="">
        static constexpr int newID()
        {
            static const unsigned int id = increment<s_idcount_>();
            return id;
        };
    };
    

    Al utilizar una función constexpr recursiva para incrementar el contador de id en tiempo de compilación, ahora podemos utilizar la función newID() con diferentes argumentos de plantilla y obtener los mismos resultados que antes, pero ahora en tiempo de compilación en lugar de en tiempo de ejecución.

Comments are closed.