| Autor |
Nachricht |
Dobi
Mitglied
Benutzerprofil
Anmeldungsdatum: 24.03.2006
Beiträge: 672
|
Dobi Mitglied
13:30:51 25.05.2012 Titel: |
TMP: Permutationen von Template-Parametern generieren |
Zitieren |
Hallo zusammen,
ich überlege gerade, ob man meine Factory-Funktion MakeBar mittels TMP oder sonstwie eleganter hinbekommen könnte, habe aber noch überhaupt keinen Ansatz. Etwas mit Andreischen typelists vielleicht?
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <memory>
struct Foo1 {};
struct Foo2 {};
struct Foo3 {};
struct BarBase {};
template<typename T1, typename T2>
struct Bar : public BarBase {};
typedef std::unique_ptr<BarBase> BarPtr;
BarPtr MakeBar( int id1, int id2 ) {
if ( id1 == 1 && id2 == 1 )
return BarPtr( new( Bar<Foo1, Foo1> ) );
else if ( id1 == 1 && id2 == 2 )
return BarPtr( new( Bar<Foo1, Foo2> ) );
else if ( id1 == 1 && id2 == 3 )
return BarPtr( new( Bar<Foo1, Foo3> ) );
else if ( id1 == 2 && id2 == 1 )
return BarPtr( new( Bar<Foo2, Foo1> ) );
else if ( id1 == 2 && id2 == 2 )
return BarPtr( new( Bar<Foo2, Foo2> ) );
else if ( id1 == 2 && id2 == 3 )
return BarPtr( new( Bar<Foo2, Foo3> ) );
else if ( id1 == 3 && id2 == 1 )
return BarPtr( new( Bar<Foo3, Foo1> ) );
else if ( id1 == 3 && id2 == 2 )
return BarPtr( new( Bar<Foo3, Foo2> ) );
else if ( id1 == 3 && id2 == 3 )
return BarPtr( new( Bar<Foo3, Foo3> ) );
return BarPtr();
}
int main() {
int userInput1( 2 );
int userInput2( 3 );
BarPtr ptr( MakeBar( userInput1, userInput2 ) );
} | |
Irgendwelche Ideen, wie man das viele Instanziieren des Klassentemplates nicht mehr manuell machen muss?
Gruß
Dobi |
|
|
|
 |
camper
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2004
Beiträge: 5798
|
camper Mitglied
14:00:14 25.05.2012 Titel: |
|
Zitieren |
Das geht, ich habe allerdings gerade keinen Compiler zur Hand, um eine fertige Lösung zu erstellen (außerdem ist das eine der Aufgaben für PI )
Kurz skizziert könnte das ungefähr so aussehen (wobei mir diese Lösung nihct besonders gut gefällt), da ohne Compiler komplett ungetest und wahrscheinlich auch mit einigen Syntaxfehlern:
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | template <typename... T>
struct typelist : std::identity<typelist<T...>> {};
template <typename... L>
struct concat_typelists : std::identity<concat_typelists<typename L::type>> {};
template <typename... T, typename... U, typename... L>
struct concat_typelists<typelist<T...>, typelist<U...>, L...> : concat_typelists<typelist<T..., U...>, L...> {};
template <std::size_t... N, typename L>
struct repeat_list;
template <std::size_t... N, typename... T>
struct repeat_list<N, typelist<T...>> : concat_typelists<typelist<T...>, repeat_list<N-1, T...>> {};
template <typename... T>
struct repeat_list<0, typelist<T...>> : typelist<> {};
template <std::size_t... N, typename L>
struct repeat_types;
template <std::size_t... N, typename... T>
struct repeat_types<N, typelist<T...>> : concat_typelists<repeat_list<N, T>...> {};
template <typename T, typename U>
void foo();
template <typename... T, typename... U>
void dispatch_helper(std::size_t i, typelist<T...>, typelist<U...>)
{
static const void (*foos[])() = { foo<T, U>... };
return foos[i]();
}
template <typename... T>
void dispatch(std::size_t i, std::size_t j)
{
using types = typelist<T...>;
using types_repeated = repeat_types<sizeof...(T), types>;
using list_repeated = repeat_list<sizeof...(T), types>;
dispatch_helper(i*sizeof...(T)+j, types_repeated(), list_repeated());
}; | | |
|
|
|
 |
pyhax
Mitglied
Benutzerprofil
Anmeldungsdatum: 22.11.2011
Beiträge: 692
|
pyhax Mitglied
12:04:20 26.05.2012 Titel: |
|
Zitieren |
| C++: | template <typename... T>
struct typelist : std::identity<typelist<T...>> {}; | |
Wie funktioniert das ? Warum erbt camper hier von std::identity ?? |
_________________ Ich kann (teilweise): C++, Python, Java(ist lange her), PHP, D (Anfänger)
|
|
 |
314159265358979__
Unregistrierter
|
314159265358979__ Unregistrierter
12:13:30 26.05.2012 Titel: |
|
Zitieren |
Das ist ein TMP-Abkürzungs-Trick. std::identity ist äquivalent zu:
| C++: | template <typename T>
struct identity
{
typedef T type;
}; | |
Da viele TMP-Algorithmen ihr Ergebnis durch ein typedef type herausgeben, lässt sich ein Algorithmus xyz
| C++: | template <typename Foo>
struct xyz
{
typedef Foo type;
}; | |
kürzer schreiben als
| C++: | template <typename Foo>
struct xyz
: identity<Foo>
{}; | |
camper lässt nun seine typelist selbst von std::identity erben. Wenn er nun als Ergebnis eine Leere Typliste haben möchte, kann er deshalb nochmal abkürzen und statt
| C++: | | : identity<typelist<>> | |
direkt
schreiben. Sein repeat_list macht davon Gebrauch. |
|
|
|
 |
314159265358979__
Unregistrierter
|
314159265358979__ Unregistrierter
12:16:07 26.05.2012 Titel: |
|
Zitieren |
Pseudo-Edit: Das "Leere" aus dem letzten Satz streichen. Geht natürlich mit allen Typlisten. |
|
|
|
 |
pyhax
Mitglied
Benutzerprofil
Anmeldungsdatum: 22.11.2011
Beiträge: 692
|
pyhax Mitglied
12:28:26 26.05.2012 Titel: |
|
Zitieren |
Ok, danke. Ich wusste vorher noch gar nicht, das man mehr als ein Variadic Template Argument haben kann. |
_________________ Ich kann (teilweise): C++, Python, Java(ist lange her), PHP, D (Anfänger)
|
|
 |
314159265358979__
Unregistrierter
|
314159265358979__ Unregistrierter
12:31:46 26.05.2012 Titel: |
|
Zitieren |
Das geht auch nur bei Klassentemplate-Spezialisierungen und Funktionstemplates wo die Parameter deduziert werden können. |
|
|
|
 |
pyhax
Mitglied
Benutzerprofil
Anmeldungsdatum: 22.11.2011
Beiträge: 692
|
pyhax Mitglied
12:34:37 26.05.2012 Titel: |
|
Zitieren |
| 314159265358979__ schrieb: | | Das geht auch nur bei Klassentemplate-Spezialisierungen und Funktionstemplates wo die Parameter deduziert werden können. |
Ja, das habe ich mir auch schon gedacht. Sonst wäre das ja nicht mehr eindeutig. |
_________________ Ich kann (teilweise): C++, Python, Java(ist lange her), PHP, D (Anfänger)
|
|
 |
Dobi
Mitglied
Benutzerprofil
Anmeldungsdatum: 24.03.2006
Beiträge: 672
|
Dobi Mitglied
22:12:31 26.05.2012 Titel: |
|
Zitieren |
Wow, super, vielen Dank. Jetzt mach ich mich mal ans Verstehen. |
|
|
|
 |
Unregistrierter
|
Unregistrierter
23:00:04 26.05.2012 Titel: |
|
Zitieren |
| 314159265358979__ schrieb: | Wenn er nun als Ergebnis eine Leere Typliste haben möchte, kann er deshalb nochmal abkürzen und statt
| C++: | | : identity<typelist<>> | |
direkt
schreiben. Sein repeat_list macht davon Gebrauch. |
Wenn ich das jetzt richtig verstehe, heißt das, dass eine Klasse von sich selbst ableiten kann? o.O |
|
|
|
 |
|
Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben. Sie können auf Beiträge in diesem Forum antworten. Sie können Ihre Beiträge in diesem Forum nicht bearbeiten. Sie können Ihre Beiträge in diesem Forum nicht löschen. Sie können an Umfragen in diesem Forum nicht mitmachen.
|
|
|
|
|