Il sistema di template C ++ può essere utilizzato per eseguire operazioni di tipo sicuro dell'algebra relazionale

7

Supponiamo che i parametri delle funzioni che rappresentano le operazioni dell'algebra relazionale siano rappresentati da singoli tipi: structs o classes. Un'operazione come join (naturale) avrà parametri di due tipi (T1, T2) come input e produrrà un valore di ritorno di un terzo tipo (T3). Esiste una relazione tra i tipi T1, T2 e T3 che in teoria possono essere conosciuti e controllati in fase di compilazione. C'è un modo per farlo usando i modelli C ++?

Esempio: assumere questi tipi di input (i dati del fornitore CJDate):

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

Questo è il tipo di output:

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

Esiste una strategia che consentirebbe (per esempio) di generare il tipo di output dagli input usando i template e quindi di essere staticamente controllato?

Divulgazione: sono un programmatore C ++ esperto e al momento non ho idea di come risolvere questo problema o dimostrare che non può essere fatto. Una soluzione in qualche altra lingua sarebbe ugualmente interessante.

Dopo alcune ulteriori indagini, mi è sembrato che la caratteristica principale mancante potesse essere il tipo di metaprogrammazione che significa la possibilità di eseguire codice arbitrario in fase di compilazione, prima della risoluzione del tipo. Il linguaggio D sembra avere quello. Mi chiedo se il comitato C ++ lo stia prendendo in considerazione.

    
posta david.pfx 27.06.2016 - 03:44
fonte

1 risposta

5

Ciò di cui stai parlando non sarà direttamente possibile in C ++ finché non avremo una qualche forma di riflessione riflessiva e di generazione di tipi basati sulla riflessione. Quindi dovrai aspettare un po '.

Il più vicino che puoi ottenere adesso è utilizzare l'ereditarietà:

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

Ovviamente, questo ti farebbe avere due membri sid separati.

In effetti, la maggior parte degli attuali tentativi di soluzioni ( tuple concatenazione typelist) si verifica nello stesso problema: come rimuovere le voci duplicate.

Potresti farlo con tuple concatenazione se hai usato un tag speciale applicato a ogni elemento tuple per dargli un "nome" di qualche tipo. Puoi farlo con qualcosa di simile:

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>>;

Puoi anche creare una forma alternativa di std::get che funzioni per nome tag, per facilitare l'accesso alla tupla: get<sid>(tpl) e così via.

Da qui, dovrai quindi eseguire una metaprogrammazione molto complicata in cui concatenerai le due tuple, ma senza duplicare le voci.

    
risposta data 27.06.2016 - 14:42
fonte

Leggi altre domande sui tag