¿Se puede usar el sistema de plantillas C ++ para realizar operaciones de tipo seguro del álgebra relacional?

7

Suponga que los parámetros de las funciones que representan operaciones del álgebra relacional están representados por tipos individuales: estructuras o clases. Una operación como la unión (natural) tendrá parámetros de dos tipos (T1, T2) como entradas y producirá un valor de retorno de un tercer tipo (T3). Existe una relación entre los tipos T1, T2 y T3 que, en teoría, se pueden conocer y verificar en el momento de la compilación. ¿Hay alguna manera de hacerlo usando plantillas de C ++?

Ejemplo: asuma estos tipos de entrada (los datos del proveedor de CJDate):

struct supplier {
  string sid;
  string sname;
  integer status;
  string city;
}
struct supplierpart {
  string sid;
  string pid;
  integer qty;
}

Este es el tipo de salida:

struct ssp_join {
  string sid;
  string pid;
  integer qty;
  string sname;
  integer status;
  string city;
}

¿Existe alguna estrategia que permita (digamos) que el tipo de salida se genere a partir de las entradas utilizando plantillas y, por lo tanto, se verifique el tipo de forma estática?

Divulgación: Soy un programador de C ++ experimentado y actualmente no tengo idea de cómo resolver este problema o probar que no se puede hacer. Una solución en otro idioma sería igualmente interesante.

Después de una investigación adicional, me pareció que la característica que faltaba de la clave podría ser el tipo de metaprogramación que significa la capacidad de ejecutar código arbitrario en el momento de la compilación, antes de la resolución de tipos. El lenguaje D parece tener eso. Me pregunto si el comité de C ++ lo está considerando.

    
pregunta david.pfx 27.06.2016 - 03:44

1 respuesta

5

Lo que está hablando no será directamente posible en C ++ hasta que obtengamos algún tipo de introspección de reflexión y generación de tipos basada en la reflexión. Así que vas a tener que esperar un rato.

Lo más cerca que puedes llegar ahora es emplear la herencia:

template<typename T1, typename T2>
struct joined : public T1, public T2
{
};

Por supuesto, esto causaría que tengas dos miembros sid separados.

De hecho, la mayoría de los intentos actuales de soluciones ( tuple typelist concatenation) se encuentran con el mismo problema: cómo eliminar entradas duplicadas.

Podría hacerlo con tuple concatenación si usara alguna etiqueta especial aplicada a cada elemento tuple para darle un "nombre" de algún tipo. Podrías hacer eso con algo como esto:

template<typename T, typename TagType>
struct tagged_type
{
  T t;
  using Tag = TagType;
};

//Various tag names
struct sid{};
struct sname{};
struct status{};
struct city{};
struct pid{};
struct qty{};

using supplier = tuple<
  tagged_type<std::string, sid>,
  tagged_type<std::string, sname>,
  tagged_type<int, status>,
  tagged_type<std::string, city>>;

using supplierpart = tuple<
  tagged_type<std::string, sid>,
  tagged_type<std::string, pid>,
  tagged_type<int, qty>>;

Incluso puedes hacer una forma alternativa de std::get que funcione por nombre de etiqueta, para facilitar el acceso a la tupla: get<sid>(tpl) , etc.

A partir de aquí, tendrá que hacer un poco de metaprogramación muy complicada donde concatene las dos tuplas, pero sin duplicar las entradas.

    
respondido por el Nicol Bolas 27.06.2016 - 14:42

Lea otras preguntas en las etiquetas