SFINAE检测非成员函数的存在

时间:2010-07-30 21:56:57

标签: c++ sfinae

是否有人知道根据是否定义了非成员方法来专门化模板的方法?我知道如果存在成员函数,有很多方法可以专门化,但我从未见过非成员函数。具体问题是专门操作员<< for shared_ptr应用运算符<<如果运营商<<为T定义,否则打印仅指针位置。如果所有类都定义了运算符<<作为成员,但不幸的是许多人使用免费功能。我想象的东西如下:

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已经有一个默认运算符&lt;&lt;输出地址,所以disable_if是不必要的。由于操作员&lt;&lt;返回一个引用,这是有效的。对于一般情况,我怀疑必须对其进行定制以反映相关函数的返回类型。

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 个答案:

答案 0 :(得分:2)

如果您使用的是C ++ 0x,则只需使用decltype。

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

如果无法输出T,那肯定会导致替换失败。你可以在C ++ 03中做类似的事情,但我不确定如何。

编辑:刚刚意识到decltype表达式实际上不会产生true或false值,也不会编译。但你明白了。试试这个。