Forum: PC-Programmierung Prüfen ob ein Wert in Variadic Template Liste vorkommt?


von CppBert (Gast)


Lesenswert?

Ich ordne per Template-Spezialisierung einem Typ eine Id zu und
möchte prüfen ob diese Id in den Parametern eines Variadic Templates
vorkommen

Wie kann ich das mit meinem alten VS2015 elegant lösen - im Internet
ist es echt schwer zwischen den C++11 bis C++17 Beispielen zu 
unterscheiden
- ich kann max C++14 nutzen, wäre aber auch schön zu wissen wie das in 
C++17 aussehen könnte
1
#include <cassert>
2
3
template<typename Type>
4
struct TypeId
5
{
6
  static int Id();
7
};
8
9
struct TypeA;
10
struct TypeB;
11
12
template<> struct TypeId<TypeA> { static int Id(){ return 0; } };
13
template<> struct TypeId<TypeB> { static int Id(){ return 1; } };
14
15
// ich habe nur den VS2015
16
template<typename ...Types>
17
bool contains(const int type_id)
18
{
19
    //...TypeId<Type>::Id() == type_id
20
}
21
22
int main()
23
{
24
    //assert(contains<TypeA, TypeB>(TypeId<TypeA>::Id()))
25
    //assert(contains<TypeA, TypeB>(TypeId<TypeB>::Id()))
26
    //assert(!contains<TypeB>(TypeId<TypeA>::Id()))
27
    return 0;
28
}

von Sven P. (Gast)


Lesenswert?

Dann roll das Parameter-Pack doch rekursiv aus.

Stichwort: Type List.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Ist die type_id nur zur Laufzeit bekannt oder schon beim Kompilieren?
Wenn zur Laufzeit: Die Werte Types::Id()... in ein Array packen und 
darin mit std::find suchen. Falls du sicher weißt dass die Werte 
sortiert sind, ist std::binary_search schneller.

von CppBert (Gast)


Lesenswert?

Sven P. schrieb:
> Dann roll das Parameter-Pack doch rekursiv aus.
>
> Stichwort: Type List.

bisher ist mir noch unklar wann man mit Head/Tail, usw. arbeitet - jedes 
mal wenn ich was finde sieht es ein bisschen anders aus

von CppBert (Gast)


Lesenswert?

Niklas G. schrieb:
> Ist die type_id nur zur Laufzeit bekannt oder schon beim
> Kompilieren?

Die type_id mit der contains aufgerufen wird ist nur zur Laufzeit 
vorhanden
die Contains-Type-Liste(und deren type_ids) aber schon zur Kompilierzeit 
und die hängt immer an einem konkreten Objekt - contains ist in diesem 
Fall auch eher ein Implements-Interface-Id<TypeA, TypeB>...

> Wenn zur Laufzeit: Die Werte Types::Id()... in ein Array packen und
> darin mit std::find suchen. Falls du sicher weißt dass die Werte
> sortiert sind, ist std::binary_search schneller.

das finde ist nicht mein Problem sondern nur die Parameter-Liste zur
kompilierzeit in die korrekte if-Konstruktion zu verwandeln

contains<TypeA, TypeB>(const int type_id) wird instanziert zu
{
  return TypeId<TypeA>::Id() == type_id || TypeId<TypeB>::Id() == 
type_id;
}

contains<TypeB>(const int type_id) wird instanziert zu
{
  return TypeId<TypeB>::Id() == type_id;
}

also "ausgerollt"

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

So?
1
template<typename ...Types>
2
bool contains(const int type_id)
3
{
4
  static constexpr int AllIds [sizeof...(Types)] { Types::Id () ... };
5
  return std::find (std::begin (AllIds), std::end(AllIds), type_id) != std::end(AllIds);
6
}

von CppBert (Gast)


Lesenswert?

Niklas G. schrieb:
> So?template<typename ...Types>
> bool contains(const int type_id)
> {
>   static constexpr int AllIds [sizeof...(Types)] { Types::Id () ... };
>   return std::find (std::begin (AllIds), std::end(AllIds), type_id) !=
> std::end(AllIds);
> }

constexpr mit VS2015 ist leider nicht so prickelnd :(

von Vincent H. (vinci)


Lesenswert?

Hier mal ein Beispiel mit Fold-Expressions:
https://godbolt.org/z/_uK48D

Um das nun auf C++14 zu übertragen müsste man die Fold-Expression 
rekursiv auflösen.

: Bearbeitet durch User
von Bert3 (Gast)


Lesenswert?

Der contains runtime parameter type_id ist kein kompiletime parameter - 
aber ich probiere mal ein wenig mit euren tips

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.