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.

Función de conversión estática y función de conversión con plantillas

Tengo una clase que envuelve algún tipo y le adjunta una Dimension. Debe ser convertible al tipo subyacente, pero solo si Dim=0. El operador de conversión no debe ser llamable en otros casos (por lo que un static_assert en la función no funcionaría para mí).

El siguiente código funciona si se elimina la construcción de enable_if, pero no en esta forma.

template<class t,="" int="" dim="">
class Unit {
    public:
    explicit Unit(T const& value): _value(value) {}

template<int d="Dim," typename="typename"></int><d =="0">::type>
operator T() { return _value; }
private:
T _value;
};

auto main() -> int
{
    auto a = double{0};
    auto u = Unit<double, 0="">{a};
    auto i = static_cast<int>(u);
    return i;
}

¿Cuál es la razón de esto y hay una solución alternativa para permitir la conversión pero también restringir la conversión?</double,>

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la que el código no funciona con la construcción enable_if es porque está aplicando SFINAE (Substitution Failure Is Not An Error) a la plantilla de la función operator T(). Esto significa que cuando Dim no es igual a 0, la función no se considerará como candidata para la resolución de sobrecarga y no será instanciada.

    Sin embargo, en este caso, el error no ocurre durante la etapa de sustitución de la plantilla de la función porque no hay un requisito duro especificado en los parámetros de la plantilla para que enable_if desencadene una falla de sustitución. Por lo tanto, el compilador intentará instanciar operator T() para cualquier valor de Dim, lo que dará lugar a un mensaje de error en tiempo de compilación.

    Para solucionar este problema, se puede utilizar un static_assert en el cuerpo de la plantilla de la función para verificar si Dim es igual a 0 y lanzar un std::logic_error si no lo es. Esto garantizará que la función siempre falle para valores de Dim no nulos, sin depender de SFINAE.

    “`c ++
    template
    class Unit {
    public:
    explicit Unit(T const& value): _value(value) {}

    operator T() {
        static_assert(Dim == 0, "Error: la dimensión debe ser cero.");
        return _value;
    }
    

    private:
    T _value;
    };

    auto main() -> int {
    auto a = double{0};
    auto u = Unit<double, 0=””>{a};
    auto i = static_cast(u);
    return i;
    }
    “`

    En esta versión del código, eliminamos la construcción enable_if, la reemplazamos por un static_assert en el cuerpo de la plantilla de la función de conversión y eliminamos la lista de parámetros de plantilla vacía. Esto asegura que el operador de conversión solo sea llamado cuando Dim es 0.

    Tenga en cuenta que el static_assert se puede reemplazar por una excepción, o puede dejar la función sin implementar para dimensiones no nulas.</double,>

Comments are closed.