SFINAE Um das Vorhandensein einer Nichtmitgliedsfunktion zu erkennen

Kennt jemand eine Methode zum Spezialisieren einer Vorlage, abhängig davon, ob eine Nicht-Member-Methode definiert ist? Ich weiß, dass es zahlreiche Möglichkeiten gibt, sich zu spezialisieren, wenn eine Mitgliedsfunktion vorhanden ist, aber ich habe noch nie ein Beispiel eines Nichtmitglieds gesehen. Das spezielle Problem besteht darin, den Operator << für shared_ptr so zu spezialisieren, dass er den Operator << anwendet, wenn der Operator << für T definiert ist, und ansonsten die bloße Zeigerposition zu drucken. Es wäre toll, wenn alle Klassen Operator << als Member definieren würden, aber leider verwenden viele freie Funktionen. Ich stelle mir so etwas vor:

template <typename T>
typename enable_if< ??? ,std::ostream &>::type operator<<( std::ostream & os, const shared_ptr<T> & ptr )
{
  if(ptr)
   return os << *ptr;
  else
   return os << "<NULL>";
}

template <typename T>
typename disable_if< ??? ,std::ostream &>::type operator<<( std::ostream & os, const shared_ptr<T> & ptr )
{
  if(ptr)
   return os << static_cast<intptr_t>( ptr.get() );
  else
   return os << "<NULL>";
}

Edit: Für die Nachwelt war hier die funktionierende Lösung. Beachten Sie, dass boost :: shared_ptr bereits einen Standardoperator << hat, der die Adresse ausgibt, sodass disable_if nicht erforderlich ist. Da der Operator << eine Referenz zurückgibt, funktioniert dies. Ich vermute, dass dies für den allgemeinen Fall angepasst werden muss, um den Rückgabetyp der fraglichen Funktion widerzuspiegeln.

template <typename T>
typename boost::enable_if_c< boost::is_reference<decltype(*static_cast<std::ostream *>(0) << *static_cast<T *>(0) )>::value, std::ostream &>::type operator<<( std::ostream & os, const boost::shared_ptr<T> & ptr )
{
  if(ptr)
   return os << *ptr;
  else
   return os << "<NULL>";
}

Antworten auf die Frage(2)

Ihre Antwort auf die Frage