Frage

In Vorlagen wie unten dargestellt, würde ich der Anruf Run(&Base::foo) ohne die Notwendigkeit gelingen mag zweimal den Basistyp zu nennen (wie in der Zusammenstellung Run<Base>(&Base::foo) Anruf erfolgt). Kann ich das haben? Möglicherweise ohne Zugabe eine Tonne Boost- Header?

Mit dem bereitgestellten Code, erhalte ich einen Fehler von:

prog.cpp:26: error: no matching function for call to ‘Run(bool (Base::*)())’

(Sie können mit dem Schnipsel Geige unter http://ideone.com/8NZkq ):

#include <iostream>

class Base {
public:
  bool foo() { return true; }
};

Base* x;

template<typename T>
struct Traits {
  typedef bool (T::*BoolMethodPtr)();
};

template<typename T>
void Run(typename Traits<T>::BoolMethodPtr check) {
  T* y = dynamic_cast<T*>(x);
  std::cout << (y->*check)();
}

int main() {
  Base y;
  x = &y;
  Run<Base>(&Base::foo);
  Run(&Base::foo); // why error?
}
War es hilfreich?

Lösung

Die T in Traits<T>::BoolMethodPtr sind in einem nicht-abgeleitete Kontext, so dass der Compiler nicht deduce automatisch aus dem Aufruf, welche Art T sein sollte. Dies liegt daran, da der Code wie folgt sein könnte:

template<typename T>
struct Traits {
  typedef bool (T::*BoolMethodPtr)();
};

template<>
struct Traits<int> {
  typedef bool (Base::*BoolMethodPtr)();
};

Run(&Base::foo); /* What should T be deduced to? Base and int are both equally possible */

Wenn Sie ohne die Traits<T> Klasse tun können, können Sie schreiben Run wie:

template<class Class>
void Run(bool (Class::*check)()) {
  Class* y = dynamic_cast<Class*>(x);
  std::cout << (y->*check)();
}

In diesem Zusammenhang kann Class auf mittlere Base abgeleitet werden

Andere Tipps

Um einen Typen auseinander zu nehmen, jede Art verwenden partielle Spezialisierung. Es gibt keine Funktion Schablonen-Teil Spezialisierung, so dass Sie direkt benötigen, um die Funktion auf ihrem Argument Typ parametrieren und den Klassentyp innerhalb abgerufen werden.

template< typename T >
struct get_host_class; // most types are not ptmfs: don't implement this

template< typename C >
struct get_host_class< bool (C::*)() > { // implement partial specialization
     typedef C host;
     typedef void sfinae; // disallow function for non ptmf arguments
};

template< typename T >
typename get_host_class<T>::sfinae Run( T check) {
    typedef T BoolMethodPtr; // or something
    typedef typename get_host_class< T >::host host;
}

Ich denke, das ein nicht davon abgeleitete Kontext ist.

  

14.8.2.5 $ / 5- „Die nicht-abgeleiteten Kontexten   sind: - Die verschachtelten-name-Bezeichner eines   Typ, der angegeben wurde unter Verwendung eines   qualifizierte Nummer. "

Ich denke, das das Zitat, das in diesem Fall gilt. Aber einige Template Götter brauchen mein Verständnis zu ratifizieren.

Wenn der Compiler versucht, ein Template-Argument zu entsprechen, es hält nur der primäre Klassentyp. Mit anderen Worten, wenn er trifft den Ausdruck:

Run(&Base::foo);

... und es ist zu herauszufinden, die Template-Parameter für Run versuchen, es hält nur die Art der foo selbst und berücksichtigt nicht, was Klasse foo ist ein Teil.

EDIT:

Und die Art der foo ist bool(Base::*)(void), aber was Sie die Compiler wollen, ist zu finden nur Base

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top