SFINAE 检测非成员函数是否存在

发布于 2024-09-12 09:16:46 字数 1325 浏览 3 评论 0原文

有谁知道根据是否定义非成员方法来专门化模板的方法吗?我知道如果成员函数存在,有很多方法可以专门化,但我从未见过非成员示例。具体问题是专门化操作员<<对于shared_ptr应用运算符<<如果运算符<<为 T 定义,否则仅打印指针位置。如果所有类都定义了operator<<,那就太好了。作为会员,但不幸的是很多使用免费功能。我正在想象类似以下的内容:

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是不必要的。由于运算符<<返回一个引用,这有效。对于一般情况,我怀疑必须对其进行定制以反映相关函数的返回类型。

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

Does anybody know of a method for specializing a template depending on whether a non-member method is defined? I know there are numerous ways for specializing if a member function exists, but I've never seen a non-member example. The specific problem is specializing the operator<< for shared_ptr to apply the operator<< if the operator<< is defined for T, and printing the mere pointer location otherwise. It would be great if all classes defined operator<< as a member, but unfortunately many use free functions. I'm imagining something like the following:

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: For posterity, here was the working solution. Note that boost::shared_ptr already has a default operator<< that outputs the address, so the disable_if is unnecessary. Since the operator<< returns a reference, this works. For the general case I suspect this would have to be tailored to reflect the return type of the function in question.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌无敌 2024-09-19 09:16:46

如果您使用的是 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 值,并且不会编译。但你明白了。试试这个。

If you are using C++0x, you could simply use decltype.

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

That'll certainly cause a substitution failure if a T cannot be output. You could probably do something similar in C++03, but I'm not sure how.

Edit: Just realised that the decltype expression doesn't actually produce a true or false value and won't compile. But you get the picture. Try this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文