c – 使用SFINAE检查全局运算符<<?

发布时间:2020-09-18 发布网站:编程之家
编程之家收集整理的这篇文章主要介绍了c – 使用SFINAE检查全局运算符<<?编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想有几个重载的全局to_string()函数,它们采用某种类型T并将其转换为其字符串表示形式.对于一般情况,我希望能够写:

template<typename T,class OutputStringType> inline
typename enable_if<!std::is_pointer<T>::value
                && has_insertion_operator<T>::value,void>::type
to_string( T const &t,OutputStringType *out ) {
  std::ostringstream o;
  o << t;
  *out = o.str();
}

到目前为止,我对has_insertion_operator的实现是:

struct sfinae_base {
  typedef char yes[1];
  typedef char no[2];
};

template<typename T>
struct has_insertion_operator : sfinae_base {
  template<typename U> static yes& test( U& );
  template<typename U> static no& test(...);

  static std::ostream &s;
  static T const &t;

  static bool const value = sizeof( test( s << t ) ) == sizeof( yes ); // line 48
};

(它借鉴了this
this.)
这似乎有效.
但是现在我想为没有运算符<<的类型设置一个重载版本的to_string.但是有自己的to_string()成员函数,即:

template<class T,class OutputStringType> inline
typename enable_if<!has_insertion_operator<T>::value
                && has_to_string<T,std::string (T::*)() const>::value,OutputStringType *out ) {
  *out = t.to_string();
}

has_to_string的实现是:

#define DECL_HAS_MEM_FN(FN_NAME)                                      \
  template<typename T,typename S>                                     \
  struct has_##FN_NAME : sfinae_base {                                \
    template<typename SignatureType,SignatureType> struct type_check; \
    template<class U> static yes& test(type_check<S,&U::FN_NAME>*);   \
    template<class U> static no& test(...);                           \
    static bool const value = sizeof( test<T>(0) ) == sizeof( yes );  \
  }

DECL_HAS_MEM_FN( to_string );

(这部分似乎工作正常.它改编自this.)
但是,当我有:

struct S {
  string to_string() const {
    return "42";
  }
};

int main() {
  string buf;
  S s;
  to_string( s,&buf ); // line 104
}

我明白了:

foo.cpp: In instantiation of ‘const bool has_insertion_operator<S>::value’:
foo.cpp:104:   instantiated from here
foo.cpp:48: error: no match for ‘operator<<’ in ‘has_insertion_operator<S>::s << has_insertion_operator<S>::t’

似乎SFINAE没有发生.如何正确编写has_insertion_operator,以确定是否为全局运算符<<可以吗? 仅供参考:我正在使用g 4.2.1(在Mac OS X上作为Xcode的一部分提供).
此外,我希望代码只是没有第三方库的标准C 03,例如Boost.

谢谢!

解决方法

我应该更忠实于 this答案.
一个有效的实施是:

namespace has_insertion_operator_impl {
  typedef char no;
  typedef char yes[2];

  struct any_t {
    template<typename T> any_t( T const& );
  };

  no operator<<( std::ostream const&,any_t const& );

  yes& test( std::ostream& );
  no test( no );

  template<typename T>
  struct has_insertion_operator {
    static std::ostream &s;
    static T const &t;
    static bool const value = sizeof( test(s << t) ) == sizeof( yes );
  };
}

template<typename T>
struct has_insertion_operator :
  has_insertion_operator_impl::has_insertion_operator<T> {
};

我相信它实际上并不依赖于SFINAE.

总结

以上是编程之家为你收集整理的c – 使用SFINAE检查全局运算符<<?全部内容,希望文章能够帮你解决c – 使用SFINAE检查全局运算符<<?所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您喜欢交流学习经验,点击链接加入编程之家官方QQ群:1065694478
编程之家官方公众号

微信公众号搜索 “ 程序精选 ” ,选择关注!

微信公众号搜索 “ 程序精选 ”
精选程序员所需精品干货内容!