2016-04-15 11 views
1

Ich verwende eine Vorlage Funktion searchByCriteria<T>, wo ich möchte die Funktion mit einem string und einem double ausführen können. Ich habe eine Liste von benutzerdefinierten Objekten mit den Attributen string und double, und ich möchte diese Funktion verwenden, um den Kriterienwert (welcher Art auch immer, vom Benutzer eingegeben) zu überprüfen, um Übereinstimmungen in dem Objekt zu überprüfen Attribute des gleichen Typs.C++ - Cast Vorlage-Objekt zu bestimmten Datentypen

I.e. Der Benutzer gibt einen doppelten Wert ein und überprüft die Objektsammlung auf übereinstimmende doppelte Werte. Der Benutzer gibt einen Zeichenfolgenwert ein und überprüft die Objektauflistung auf übereinstimmende Zeichenfolgenwerte.

Das Problem, das ich habe, ist, sobald der Wert eingegeben wird, wird es an eine andere Vorlage-Funktion übergeben, um mit den Elementen in der Liste überprüft werden. Und an diesem Punkt muss das Objekt T, das als Parameter übergeben wird, entweder in ein Double oder in eine Zeichenfolge konvertiert werden, um Übereinstimmungen überprüfen zu können. Hier

ist der Code für diesen Teil:

Wie Sie sehen können, der Parameterwert criteria wieder in einen bestimmten Datentyp vor der while-Schleife konvertiert werden muss eingegeben werden für die Spiele zu überprüfen. Ich bin bei einem leichten Verlust darüber, wie dies zu tun ist, da mir keine Casting-Methoden in C++ bekannt sind, die in dieser Situation nützlich wären.

Das einzige, was ich denken kann, wäre so etwas wie:

try 
{ 
    //example method 
    convertToDouble(criteria); 
} 
catch (SomeKindOfNumberException ex) 
{ 
    //cannot be a double 
    //so must be string 
    convertToString(criteria); 
} 

Jede Hilfe wird sehr geschätzt.

Danke, Mark

Antwort

1

Wie wäre es so etwas?

#include <iostream> 

template<typename T> 
T FuncB(T x) { 
    std::cout << "generic T "; 
    return x; 
} 

template<> 
double FuncB<double>(double x) { 
    std::cout << "double "; 
    return 0.123; 
} 

template<> 
std::string FuncB<std::string>(std::string x) { 
    std::cout << "string "; 
    return "xyz"; 
} 

template <typename T> 
void FuncA(T param) { 
    std::cout << "FuncA: "; 
    T tmp = FuncB(param); 
    std::cout << tmp << std::endl; 
} 

int main() { 
    std::string s = "abc"; 

    FuncA(0.1); 
    FuncA(s); 
    FuncA(1); 
} 

FuncA kann jede T empfangen, aber es nutzt FuncB, die für bestimmte Arten spezialisiert. Wenn Sie möchten, können Sie FuncB (T) behalten oder löschen, um unbekannte Typen zu unterstützen/zu vermeiden.

Der Ausgang des vorherigen Code wie folgt aussieht:

FuncA: double 0.123 
FuncA: string xyz 
FuncA: generic T 1 
+0

Hallo, vielen Dank dafür. Wenn ich in Ihrem Beispiel diese Funktionen verwenden möchte, um ihre jeweiligen int/double/T-Werte zurückzugeben und diese in einer Variablen zu speichern, wie könnte ich das tun? – marcuthh

+0

@marcuthh: Ich habe gerade das – purpletentacle

+0

aufgenommen Dies hat perfekt funktioniert. Vielen Dank für Ihre Zeit! – marcuthh

1

Vielleicht können Sie eine Criterion<T> Klasse, die Benutzerwert und den Test zu dieser Klasse delegieren:

template<class T> 
class Criterion { 
    T m_value; 
public: 
    Criterion(T&& value) // allow implicit conversion 
    : m_value(std::forward<T>(value)) {} 
    bool appliesTo(const TransactionList &l); // provide default implementation if any 
} 

template<> 
inline bool Criterion<double>::appliesTo(const TransactionList &l) { 
    /* check against double field */ 
} 

template<> 
inline bool Criterion<std::string>::appliesTo(const TransactionList &l) { 
    /* check against string field */ 
} 

Dann wird Ihr Algorithmus aussehen wird wie folgt:

template <typename T> 
const TransactionList TransactionList::getTransactionsForSearchCriteria(Criterion<T> criteria) const { 
    TransactionList copy(*this); 
    TransactionList ret; 
    while (copy.size() > 0) 
    { 
     if (criteria.appliesTo(copy)) 
     { 
      //flag as match 
     } 
    } 
} 
0

Also Ihr T Objekt ist ein Co ntainer, und Sie haben uns nicht viele Informationen darüber gegeben, aber wenn Sie vector s intern zu dem Objekt verwenden, um die Objekte zu enthalten, werden Sie weit voraus sein.

Zweitens, wenn Sie eine pair verwenden sollten, um Ihre vector s zu enthalten, können Sie get nutzen, um das richtige Mitglied auszuwählen.

Also, für die Zwecke der Erstellung einer schriftlichen Antwort mein TransactionList Objekt wird wie folgt aussehen:

typedef pair<vector<string>, vector<double>> TransactionList; 

Dann können wir Ihre Funktion umschreiben:

template <typename T> 
TransactionList getTransactionsForSearchCriteria(TransactionList result, T criteria) { 
    auto& attribute = get<vector<T>>(result); 
    auto it = find(attribute.begin(), attribute.end(), criteria); 

    //check that criteria matches transaction attribute 
    if(it != attribute.end()) { 
     //flag as match 
    } 
    //guessing what you want to do with this: attribute.insert(it, criteria); return result; 
} 

Wenn Sie, dass die Listen sicherstellen konnten, waren Der Standard wird nach sortierten Standards sortiert. Der Standard bietet eine binäre Suchfunktionalität, die Ihre Leistung für große Sammlungen erheblich verbessern würde:

template <typename T> 
transactionList getTransactionsForSearchCriteria(transactionList result, T criteria) { 
    auto& attribute = get<vector<T>>(result); 
    auto it = lower_bound(attribute.begin(), attribute.end(), criteria); 

    //check that criteria matches transaction attribute 
    if(it != attribute.end() && *it == criteria) { 
     //flag as match 
    } 
    //guessing what you want to do with this: attribute.insert(it, criteria); return result; 
} 

Soweit zu bestimmen, ob Ihre eingegebenen Wert ein string oder ein double ist, wenn TransactionList result, nehmen Sie alle Eingaben als string dann mit, ob Sie den gesamten string erfolgreich in eine double verbrauchen kann: Forcing String to int Function to Consume Entire String

size_t size; 
double num; 
string i; 
cin >> i; 

if(sscanf(i.c_str(), "%lf%n", &num, &size) == 1 && size == i.size()) { 
    result = getTransactionsForSearchCriteria(result, num); 
} else { 
    result = getTransaztionsForSearchCriteria(result, i); 
} 

Live Example