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,>
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ónoperator T()
. Esto significa que cuandoDim
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á instanciaroperator T()
para cualquier valor deDim
, 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 siDim
es igual a 0 y lanzar unstd::logic_error
si no lo es. Esto garantizará que la función siempre falle para valores deDim
no nulos, sin depender de SFINAE.“`c ++
template
class Unit {
public:
explicit Unit(T const& value): _value(value) {}
private:
T _value;
};
auto main() -> int {(u);
auto a = double{0};
auto u = Unit<double, 0=””>{a};
auto i = static_cast
return i;
}
“`
En esta versión del código, eliminamos la construcción
enable_if
, la reemplazamos por unstatic_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 cuandoDim
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,>