0

Ich habe eine Datenbank, die 4 Arten von Indizes hat. Jeder Indextyp hat eine Sortierreihenfolge. Das heißt, wenn Sie den statischen Indextyp kennen, dann gibt es einen richtigen Funktor, der zum Sortieren der Objekte in diesem Index verwendet wird, und er ist auch bekannt, sobald Sie den Indextyp kennen, d. H. Statisch zum Zeitpunkt der Kompilierung.C++ Transport laufzeitbedingten Typ Informationen

Die Datenbank verfügt über eine Funktion, die eine Laufzeitwechselanweisung enthält, um zu entscheiden, mit welchem ​​Index zu sprechen ist. Ich möchte, dass diese Funktion Laufzeitinformationen aus dem Index zurückgibt (meistens Iteratoren), aber auch den zu verwendenden statischen Auftragstyp.

Um die Absicht zu zeigen, hier ist ein Pseudo-Code. Es funktioniert nicht wie es ist ... könnte Template-Spezialisierung verwendet werden, um getLookupInfo zu schreiben (der Rückgabetyp würde polymorph). Hinweis: Ich möchte keine virtuellen Dateien verwenden.

template <typename Iterator, typename Order> 
struct LookupInfo { 
    typedef Order order; 
    uint64_t cost; 
    Iterator it1, it2, it3, it4; 
}; 

LookupInfo Database::getLookupInfo(LookupData data) 
{ 
    if (data == ....) { 
    return LookupInfo<Iterator1, Order1>(); 
    } 
    return LookupInfo<Iterator2, Order2>(); 
} 

some_function(LookupInfo lookup_info) { 
    vector<Record> records(lookup_info.begin(), lookup_info.end()); 
    sort(records.begin(), records.end(), lookup_info::order()); 
} 

Ist so etwas überhaupt möglich?

+0

Ich bin gespannt, wie Sie erwarten, dass 'getLookupInfo' funktioniert. Ich sehe nicht, wie es heißen könnte. Die Rückgabeanweisungen stimmen nicht mit dem Rückgabetyp überein, was bedeutet, dass Sie entweder Polymorphismus oder Template-Spezialisierung benötigen. – AndyG

+0

Andy - ja - da schaffe ich es nicht, die Schleife zu schließen. Das Code-Snippet funktioniert nicht, es soll mehr zeigen, was ich tun möchte. Und Sie haben Recht, der Trick ist irgendwie, dass der Rückgabetyp von getLookupInfo mir jedes Mal einen anderen Typ zurückgibt. Ich möchte jedoch keine virtuellen Dateien, daher würde ich gerne die Template-Spezialisierung verwenden. Aber selbst das IMHO ist knifflig. Die Essenz meiner Frage ist wahrscheinlich: Wie verwende ich Template-Spezialisierung, um getLookupInfo zu schreiben? – Frank

+0

Der Trick besteht darin, alles in einen Typ zu verwandeln ... Ich könnte Ihnen vielleicht helfen, wenn Sie mir einen Pseudo-Code geben, wie Sie ihn nennen möchten (ohne Template-Spezialisierung). – AndyG

Antwort

0

Sie könnten es tun, indem Sie Ihre getLookupInfo -> wenden Sie some_function Sequenz in eine einzige Dispatch-Sequenz. Erstens, Ihre Definition von some_function lässt korrigieren um die Tatsache widerzuspiegeln, dass es eine Template-Funktion ist:

template<typename LookupInfo> 
void some_function(LookupInfo lookup) 
{ 
    vector<Record> records(lookup_info.begin(), lookup_info.end()); 
    sort(records.begin(), records.end(), lookup_info::order()); 
} 

Als nächstes führen ein Helfer Funktors es aufzurufen (aus Gründen, ich unten bespreche ich kann das nicht überspringen, so sehr Ich möchte):

template<typename LookupInfo> 
struct some_functor 
{ 
    void operator()(LookupInfo lookup_info) 
    { 
     some_function<LookupInfo>(lookup_info); 
    } 
}; 

Jetzt für den Versand Trick. Vergessen Sie Ihre getLookupInfo Funktion oben und stattdessen definieren:

template<template <class L> class F> 
void dispatchLookupInfo(int data) 
{ 
    if (data == 0) { 
    auto lookup = LookupInfo<Iterator1, Order1>(); 
    F<LookupInfo<Iterator1, Order1>> fn; 
    fn(lookup); 
    } 
    else { 
    auto lookup = LookupInfo<Iterator2, Order2>(); 
    F<LookupInfo<Iterator2, Order2>> fn; 
    fn(lookup); 
    } 
} 

Hinweis ich hier vorgeben, dass data ist ein int, wie Sie sagten, es sein könnte. So wie Sie sehen können, anstatt die LookupInfo zu erhalten und dann die Funktion separat aufzurufen, machen wir es auf einmal. Hier verwendet dispatchLookupInfo einen Template-Template-Parameter, so dass er jede Funktion spezialisieren kann. Das kommt zu dem Punkt zurück, dass ich einen Helfer-Funktor benötige: Ich konnte keinen Weg finden, eine Funktionsschablone (anstelle einer Klassenschablone) als Vorlagenschablonenparameter zu übergeben. Wie auch immer, ich glaube, es erfüllt Ihre Anforderung, keine virtuellen Anrufe zu tätigen. Ihr letzter Aufruf könnte folgendermaßen aussehen:

dispatchLookupInfo<some_functor>(0);