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.

Trabajando alrededor de las limitaciones de los miembros de datos estáticos `constexpr` con el mismo tipo que la clase encapsuladora.

Quiero dar capacidades constexpr a una clase Color que se ve así:

// color.hpp
struct Color
{
    Color(int r, int g, int b, int a);
    static const Color Red;
    // ...
};

// color.cpp
Color::Color(int r, int g, int b, int a) { /* ... */ }
const Color Color::Red(255, 0, 0, 255);
// ...

Mi deseo es mantener sin cambios la API de esta clase, por lo tanto, me gustaría eliminar por completo color.cpp y hacer estos cambios en el archivo de encabezado:

// color.hpp
struct Color
{
    constexpr Color(int r, int g, int b, int a) { /* ... */ }
    inline static constexpr Color Red{255, 0, 0, 255};
    // ...
};

Sin embargo, el código anterior no se compila ya que los miembros de datos estáticos constexpr con el mismo tipo que la clase contenedora no están permitidos en C++.

Por supuesto, podría cambiar la API a algo como ColorConstants::Red y mover el objeto Red fuera de la clase, pero no quiero romper a los usuarios existentes.

La única solución alternativa que se me ocurrió se parece a esto:

// color.hpp
struct Color 
{
private:
    struct ColorInit 
    {
        int r, g, b, a;
        constexpr ColorInit(int r, int g, int b, int a) { /* ... */ }
        constexpr inline operator Color() const { /* ... */ }
    }

public:
    constexpr Color(int r, int g, int b, int a) { /* ... */ }
    inline static constexpr ColorInit Red{255, 0, 0, 255};
};

La solución alternativa anterior permite que la mayoría del código existente que utiliza Color se siga compilando después de los cambios, pero obviamente falla cada vez que Red no se usa en un contexto donde se requiera una conversión implícita a Color.

Entonces, mi pregunta es: ¿es posible encontrar una solución para evitar la limitación de constexpr mencionada anteriormente, convirtiendo Red en una expresión constante, manteniendo al mismo tiempo la sintaxis original Color::Red y evitando romper el código existente?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    A partir de C++17, no es posible tener un miembro de datos estático constexpr del mismo tipo que la clase que lo contiene. Por lo tanto, la solución propuesta en la pregunta es una opción para mantener la sintaxis original de Color::Red mientras se permite que Red sea una expresión constante.

    Otra opción podría ser usar una función constexpr en lugar de un constructor constexpr para crear el objeto Red dentro de la definición de la clase, de la siguiente manera:

    // color.hpp
    struct Color
    {
        constexpr Color(int r, int g, int b, int a) { /* ... */ }
        static constexpr Color Red() { return {255, 0, 0, 255}; }
        // ...
    };
    

    Esto permite utilizar Red como una expresión constante, a la vez que se conserva la sintaxis original de Color::Red. Sin embargo, el código existente que utiliza Color::Red como un miembro de datos estático debería actualizarse para utilizar Color::Red() en su lugar.

    En última instancia, la decisión de si utilizar la solución propuesta o actualizar la API depende de los requisitos y restricciones específicas del proyecto.

Comments are closed.