Mam wiele niestandardowych typów danych w jednym z moich projektów, które mają wspólną klasę podstawową. Moje dane (pochodzące z bazy danych) mają typ danych, który wyróżnia element wyliczeniowy klasy bazowej. Moja architektura umożliwia specyficzny typ danych, który specjalizuje się w klasie pochodnej lub może być obsługiwany przez klasę podstawową.Optymalizacja zamiany szablonu przełącznika
Kiedy skonstruować moje konkretne typy danych i normalnie wywołać konstruktor bezpośrednio:
Special_Type_X a = Special_Type_X("34.34:fdfh-78");
a.getFoo();
Jest jakiś szablon magia, która umożliwia również konstruowanie to tak:
Type_Helper<Base_Type::special_type_x>::Type a = Base_Type::construct<Base_Type::special_type_x>("34.34:fdfh-78");
a.getFoo();
Dla niektórych wartościach wpisz enum, więc nie może być specjalizacji, więc
Type_Helper<Base_Type::non_specialized_type_1>::Type == Base_Type
Gdy im Pobieranie danych z bazy danych typ danych nie jest znany w czasie kompilacji więc istnieje trzecia droga do skonstruowania typów danych (z QVariant):
Base_Type a = Base_Type::construct(Base_type::whatever,"[email protected]{3,3}");
Ale oczywiście chcę prawidłowe konstruktor być nazywany, więc wdrożenie tej metody wykorzystywane wyglądać:
switch(t) {
case Base_Type::special_type_x:
return Base_Type::construct<Base_Type::special_type_x>(var);
case Base_Type::non_specialized_type_1:
return Base_Type::construct<Base_Type::non_specialized_type_1>(var);
case Base_Type::whatever:
return Base_Type::construct<Base_Type::whatever>(var);
//.....
}
Ten kod jest powtarzalne, a ponieważ klasa bazowa może obsługiwać nowe typy (dodawane do wyliczenia), jak również, wymyśliłem następujące rozwiązanie:
//Helper Template Method
template <Base_Type::type_enum bt_itr>
Base_Type construct_switch(const Base_Type::type_enum& bt, const QVariant& v)
{
if(bt_itr==bt)
return Base_Type::construct<bt_itr>(v);
return construct_switch<(Base_Type::type_enum)(bt_itr+1)>(bt,v);
}
//Specialization for the last available (dummy type): num_types
template <>
Base_Type construct_switch<Base_Type::num_types>(const Base_Type::type_enum& bt, const QVariant&)
{
qWarning() << "Type"<<bt<<"could not be constructed";
return Base_Type(); //creates an invalid Custom Type
}
A moja oryginalna instrukcja switch otrzymuje brzmienie:
return construct_switch<(Base_Type::type_enum)0>(t,var);
to rozwiązanie działa zgodnie z oczekiwaniami. Skompilowany kod jest jednak inny. O ile oryginalna instrukcja przełączania miała złożoność O (1), nowa aplikacja skutkuje złożonością O (n). Wygenerowany kod rekursywnie wywołuje moją metodę pomocnika, dopóki nie znajdzie prawidłowego wpisu. Dlaczego kompilator nie może zoptymalizować tego poprawnie? Czy istnieją lepsze sposoby rozwiązania tego problemu?
podobny problem: Replaceing switch statements when interfaceing between templated and non-templated code
należy wspomnieć, że chciałbym uniknąć C++ 11 i C++ 14 i trzymać się C++ 03.
To dobre rozwiązanie! Jakie są moje opcje podczas używania C++ 03? – Dreamcooled
@dreamcooled zaktualizuj swój kompilator, użyj instrukcji połączonych '' ', użyj narzędzia do wygenerowania kodu, skopiuj makaron, użyj makr preprocesora do wygenerowania kodu. – Yakk
Kompilacja zaktualizowana. Działa idealnie. Dzięki. – Dreamcooled