Forum: PC-Programmierung C++17 Simple if/else Konstruktion durch Variadic Template ersetzbar?


von CppBert3 (Gast)


Angehängte Dateien:

Lesenswert?

gibt es einen elegante Möglichkeit mit C++17/Variadic templates diese 
Routine zu implementieren?
1
Base* implements(int id)
2
{
3
    if( id == InterfaceId<InterfaceA>::id 
4
        || id == InterfaceId<InterfaceC>::id ) return this;
5
    return nullptr;
6
}

für das ganze Beispiel siehe Anhang oder zum Online kompilieren: 
https://onlinegdb.com/B1fKVB0KV

von Vincent H. (vinci)


Lesenswert?

1
    if (((id == InterfaceId<Interface>::id) || ... ))
2
      return this;

von CppBert3 (Gast)


Lesenswert?

ich hänge noch sehr tief in C++03 und wandere langsam zu C++11...

Einfach und sehr kurz - vielen Dank

von M.K. B. (mkbit)


Lesenswert?

Du könntest die Methode implements() noch constexpr machen. Damit kannst 
du diese dann auch für andere Entscheidungen zur Compilezeit nutzen.

von CppBert3 (Gast)


Lesenswert?

gemacht - Danke

von CppBert3 (Gast)


Lesenswert?

noch eine Frage - das pure || folding sieht ja noch einfach aus aber was 
ist wenn dazwischen noch Operationen kommen?
1
void typed_throw(int id)
2
{
3
    // <-- wie kann man dieses If mit C++17 aus dem Interface-Parameter pack generieren lassen?
4
    if( id == InterfaceId<InterfaceA>::id ) throw static_cast<InterfaceA*>(this);
5
    if( id == InterfaceId<InterfaceB>::id ) throw static_cast<InterfaceC*>(this);
6
    throw this;
7
}

zum Online-Kompilieren:
https://onlinegdb.com/SJRfjkf9N

gibt es da auch was in C++17

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Lang aber lesbar:
1
  template <typename Itf>
2
  bool typed_throw_helper(int id) {
3
      if (InterfaceId<Itf>::id == id)
4
        throw static_cast<Itf*> (this);
5
      return false;
6
  }
7
  void typed_throw(int id)
8
  {
9
    static_cast<void> ((false || ... || typed_throw_helper<Interface> (id)));
10
    throw this;
11
  }
Kurz aber weniger lesbar:
1
  void typed_throw2(int id)
2
  {
3
      static_cast<void> ((false || ... || (InterfaceId<Interface>::id == id && (throw static_cast<Interface*> (this), true))));
4
      throw this;
5
  }

Bei "throw this" treffen aber alle "catch" Statements zu, weil Test eben 
von allen Interfaces abgeleitet wird.

von Ntldr -. (ntldr)


Lesenswert?

Ich hätte das jetzt so gemacht:
1
template<typename T, typename... Args>
2
void typed_throw_helper(int id)
3
{
4
    if(id == InterfaceId<T>::id)
5
        throw reinterpret_cast<T*>(this);
6
    if constexpr(sizeof...(Args) > 0)
7
        typed_throw<Args...>(id);
8
    else 
9
        throw this;
10
}
11
12
void typed_throw(int id)
13
{
14
    return typed_throw_helper<Interface...>();
15
}

Ginge zwar auch wie oben mit einer Hilfsfunktion (die genau dann wirft, 
wenn die Id stimmt), aber das ist mMn etwas unsauberer.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Ntldr -. schrieb:
> aber das ist mMn etwas unsauberer.

Kompiliert dafür aber schneller. Rekursive templates brauchen immer 
extra lange, und die maximale Tiefe ist beschränkt.

von CppBert3 (Gast)


Lesenswert?

@Niklas G.

Danke - das mit throw this war nur Random Beispiel Code :)

von M.K. B. (mkbit)


Lesenswert?

Das Video beschreibt ein Refactoring von einem ähnlichen Problem.
Relativ weit am Ende kommt der Trick indem man eine initializer List 
verwendet.

https://m.youtube.com/watch?v=VXi0AOQ0PF0&feature=youtu.be

von Vincent H. (vinci)


Lesenswert?

M.K. B. schrieb:
> Das Video beschreibt ein Refactoring von einem ähnlichen Problem.
> Relativ weit am Ende kommt der Trick indem man eine initializer List
> verwendet.
>
> https://m.youtube.com/watch?v=VXi0AOQ0PF0&feature=youtu.be

Genau den Trick braucht man auf Grund von Fold-Expressions eben nicht 
mehr...

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.