Los tipos parametrizados, como las plantillas C++, son algo bueno, pero la mayoría de las veces solo pueden parametrizarse por otros tipos.¿Hay un lenguaje de programación donde los tipos se pueden parametrizar por valores?
Sin embargo, hay un caso especial en C++ en el que es posible parametrizar una plantilla por un número entero. Por ejemplo, las matrices de longitud fija son un caso de uso típico:
template<typename T, int SIZE> class FixedArray
{
T m_values[SIZE];
public:
int getElementCount() const { return SIZE; }
T operator[] (int i) const {
if (i<0 || i>=SIZE)
throw;
else
return m_values[i];
}
};
void f()
{
FixedArray<float, 5> float_array; // Declares a fixed array of 5 floats.
//The size is known at compile time, and values are allocated on the stack.
}
enteros y punteros Sólo constantes están permitidos en C++, pero creo que podría ser interesante utilizar cualquier valor de parametrización (flotadores, las instancias de clase, etc. .). Esto podría permitir expresar condiciones previas en tiempo de compilación (generalmente se especifica informalmente en la documentación), y verificarlas automáticamente en el tiempo de ejecución. Por ejemplo, aquí es una plantilla de "Intervalo" en un hipotético C++ dialecto:
// Interval of type T between TMin and TMax.
template<typename T, T TMin, T TMax> class Interval
{
T m_value;
public:
Interval(int val) { *this = val; }
Interval& operator = (T val) {
//check that 'val is in [TMin, TMax] and set the value if so, throw error if not
if (val < TMin || val > TMax)
throw;
else
m_value = val;
return *this;
};
operator T() const { return m_value; }
}
// Now define a f function which is only allowing a float between O and 1
// Usually, that kind of function is taking a float parameter with the doc saying "the float is in 0-1 range". But with our Interval template we have
// that constraint expressed in the type directly.
float f(Interval<float, 0, 1> bounded_value)
{
// No need to check for boundaries here, since the template asserts at compile-time that the interval is valid
return ...;
}
// Example usage
void main();
{
float val = 0.5;
Interval<float, 0, 1> sample_interval = val; // OK. The boundary check is done once at runtime.
f(sample_interval); // OK. No check, because it is asserted by the type constraint at compile-time.
// This can prevent endless precondition testing within an algorithm always using the same interval
sample_interval = 3*val; // Exception at runtime because the constraint is no longer satisfied
f(sample_interval); // If I am here, I am sure that the interval is valid. But it is not the case in that example.
}
Lo que podría ser interesante entonces sería la de expresar las relaciones entre estos tipos. Por ejemplo, expresar la regla para asignar un Intervalo A a otro Intervalo B con otros límites, o simplemente una regla para asignar un valor a un Intervalo, con todo marcado en tiempo de compilación.
¿Hay algún lenguaje con este tipo de parametrización (o un enfoque similar), o todavía se debe inventar? ¿Algún trabajo de investigación útil?
Pascal tiene subrangos de tipos integrales que pueden verse como un caso especial de esto. – Joey