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.

Error en el operador de conversión de plantilla en GCC: ¿Hay alguna solución alternativa?

Quiero tener una clase que represente una unidad con algún tipo de dimensión. Esto debería expresar algo como 1,5m^2. Se debe permitir una multiplicación escalar con algún tipo y una unidad sin dimensión debería comportarse exactamente como el tipo subyacente. Aquí está mi solución:

include

template
class Unit {
public:
explicit Unit(T t): _value(t) {}

template<int D = Dim, typename std::enable_if_t<D==0, int> = 0>
operator T() { static_assert(Dim==0, ""); return _value; } //static_assert no es necesario, pero da error si la plantilla se elimina
T _value;

};

template
auto operator*(S s, Unit<T,Dim> unit)
{
return Unit<T, Dim>(s * unit._value);
}

auto main() -> int
{
auto i = double{0};

//Prueba escalar
auto escalar = int{0};
auto x = Unit<double,1>(i);
auto prueba = escalar * x;

//Prueba de conversión
auto y = Unit<double,0>(i);
return y + i;
}

Esto funciona perfectamente bien en clang (https://godbolt.org/z/8Pev7W6Y1). Sin embargo, debido a un error de GCC con los operadores de conversión con plantilla (https://stackoverflow.com/questions/70168022/conversion-operator-gcc-vs-clang), esto no funciona en GCC.

No es posible eliminar la construcción SFINAE porque (correctamente) se ejecuta en el static_assert.

¿Tienes alguna idea de un código equivalente que también funcione en GCC? El código debería funcionar en C++17 con ambos compiladores.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Desafortunadamente, debido al error de GCC con los operadores de conversión con plantilla, no es posible proporcionar un código equivalente que funcione con ambos compiladores en C++17. Una posible solución alternativa es usar un operador de conversión sin plantilla en su lugar:

    #include <type_traits>
    
    template<typename t,="" int="" dim="">
    class Unit {
    public:
        explicit Unit(T t): _value(t) {}
    
        operator T() { static_assert(Dim==0, ""); return _value; }
        T _value;
    };
    
    template<typename s,="" typename="" t,="" int="" dim="">
    auto operator*(S s, Unit<t,dim> unit)
    {
        return Unit<t, dim="">(s * unit._value);
    }
    
    auto main() -> int
    {
        auto i = double{0};
    
        // Prueba escalar
        auto scalar = int{0};
        auto x = Unit<double,1>(i);
        auto test = scalar * x;
    
        // Prueba de conversión
        auto y = Unit<double,0>(i);
        return y + i;
    }
    

    Este código debería funcionar tanto en Clang como en GCC, pero puede tener consecuencias no deseadas según su caso de uso. También vale la pena señalar que esta solución alternativa puede no ser viable en el futuro si y cuando se corrija el error de GCC.</double,0></double,1></t,></t,dim>

Comments are closed.