SFINAE Para detectar la existencia de funciones no miembro

¿Alguien sabe de un método para especializar una plantilla dependiendo de si se define un método no miembro? Sé que hay numerosas formas de especializarse si existe una función miembro, pero nunca he visto un ejemplo de no miembro. El problema específico es especializar el operador << para shared_ptr para aplicar el operador << si el operador << está definido para T, e imprimir la mera ubicación del puntero de lo contrario. Sería genial si todas las clases definieran al operador << como miembro, pero desafortunadamente muchos usan funciones gratuitas. Me estoy imaginando algo como lo siguiente:

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>";
}

Editar: Para la posteridad, aquí estaba la solución de trabajo. Tenga en cuenta que boost :: shared_ptr ya tiene un operador predeterminado << que genera la dirección, por lo que deshabilitar if es innecesario. Como el operador << devuelve una referencia, esto funciona. Para el caso general, sospecho que esto tendría que adaptarse para reflejar el tipo de retorno de la función en cuestión.

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>";
}

Respuestas a la pregunta(1)

Su respuesta a la pregunta