c++ - Principios de diseño detrás de std:: ratio<>
c++11 metaprogramming (4)
Estaba mirando la clase std::ratio<>
del estándar C ++ 11 que permite hacer aritmética racional en tiempo de compilación.
Encontré el diseño de la plantilla y las operaciones implementadas con clases demasiado complejas y no encontré ninguna razón por la que no pudieran usar un enfoque más directo e intuitivo al implementar una clase racional realmente simple y definir funciones constexpr
para los operadores. El resultado hubiera sido una clase más fácil de usar y las ventajas en tiempo de compilación se hubieran mantenido.
¿Alguien tiene alguna idea de las ventajas del diseño actual de std::ratio<>
comparación con una implementación de clase simple utilizando constexpr
? En realidad, no consigo encontrar ninguna ventaja en la implementación actual.
Definiendo funciones constexpr para el operador.
Aún puedes hacer esto en la parte superior de la existente std::ratio
:
#include <ratio>
// Variable template so that we have a value
template<
std::intmax_t Num,
std::intmax_t Denom = 1
>
auto ratio_ = std::ratio<Num, Denom>{};
// Repeat for all the operators
template<
std::intmax_t A,
std::intmax_t B,
std::intmax_t C,
std::intmax_t D
>
constexpr typename std::ratio_add<std::ratio<A, B>, std::ratio<C, D>>::type
operator+(std::ratio<A, B>, std::ratio<C, D>) {}
// Printing operator
template<
std::intmax_t A,
std::intmax_t B
>
std::ostream &operator<<(std::ostream &os, std::ratio<A, B> r) {
return os << decltype(r)::num << "/" << decltype(r)::den;
}
#include <iostream>
int main() {
std::cout << ratio_<1,2> + ratio_<1,3> << std::endl;
return 0;
}
5/6
Cuando se propuso N2661 , ninguno de los autores de la propuesta tuvo acceso a un compilador que implementó constexpr
. Y ninguno de nosotros estaba dispuesto a proponer algo que no pudiéramos construir y probar. Por lo tanto, si un mejor diseño podría haberse hecho con constexpr
ni siquiera fue parte de la consideración para el diseño. El diseño se basó únicamente en las herramientas disponibles para los autores en ese momento.
La solución constexpr resuelve un problema completamente diferente. std::ratio
fue creado para ser usado como un puente entre variables que usan diferentes unidades, no como una herramienta matemática. En estas circunstancias, es absolutamente necesario que la proporción sea parte del tipo. La solución constexpr no funcionará allí. Por ejemplo, no será posible implementar std::duration
sin un espacio de tiempo de ejecución y costos de tiempo de ejecución, porque cada objeto de duración tendría que llevar su información de denominador / denominador dentro del objeto.
std::ratio
y sus mecanismos circundantes siempre se ejecutarán en tiempo de compilación, en virtud de la metaprogramación de plantillas y la manipulación de tipos. constexpr
solo se requiere para ejecutarse en tiempo de ejecución cuando las instalaciones de C ++ requieren una expresión constante (como los parámetros de una plantilla o la inicialización de una variable constexpr
).
Entonces, ¿qué es más importante para usted: la ejecución en tiempo de compilación, o ser "más directo e intuitivo"?