SFINAE Для обнаружения существования функции, не являющейся членом - PullRequest
3 голосов
/ 31 июля 2010

Кто-нибудь знает метод для специализации шаблона в зависимости от того, определен ли метод, не являющийся членом?Я знаю, что существует множество способов специализироваться, если функция-член существует, но я никогда не видел пример, не являющийся членом.Конкретной проблемой является специализация оператора << для shared_ptr для применения оператора <<, если оператор << определен для T, и печать простого расположения указателя в противном случае.Было бы замечательно, если бы все классы определяли оператор << как член, но, к сожалению, многие используют бесплатные функции.Я представляю что-то вроде следующего: </p>

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

Редактировать: для потомков, вот было рабочее решение.Обратите внимание, что boost :: shared_ptr уже имеет оператор по умолчанию <<, который выводит адрес, поэтому disable_if не нужен.Поскольку оператор << возвращает ссылку, это работает.Я подозреваю, что для общего случая это должно быть адаптировано для отражения типа возврата рассматриваемой функции. </p>

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

1 Ответ

2 голосов
/ 31 июля 2010

Если вы используете C ++ 0x, вы можете просто использовать decltype.

template<typename Char, typename CharTraits, typename T>
        decltype(
            *(std::basic_ostream<Char, CharTraits>*)(nullptr) << *(T*)(nullptr)
        )

Это, безусловно, вызовет ошибку замещения, если T не может быть выведен. Возможно, вы могли бы сделать что-то подобное в C ++ 03, но я не уверен, как.

Edit: только что понял, что выражение decltype на самом деле не дает значения true или false и не будет компилироваться Но вы получите картину. Попробуйте это.

...