C++ 使用SFINAE检查全局运算符<&书信电报;?

C++ 使用SFINAE检查全局运算符<&书信电报;?,c++,templates,sfinae,C++,Templates,Sfinae,我希望有几个重载的、全局的to_string()函数,这些函数采用某种类型T,并将其转换为字符串表示形式。对于一般情况,我希望能够写: template<typename T,class OutputStringType> inline typename enable_if<!std::is_pointer<T>::value && has_insertion_operator<T>::value,

我希望有几个重载的、全局的
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();
}
(它从 及) 这似乎奏效了。
但是现在我想为没有
运算符的类型提供一个重载版本的
to_string
,第48行
值的初始值设定项不在SFINAE工作的上下文中。尝试将表达式移动到函数声明中

#include <iostream>

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

template<typename T>
struct has_insertion_operator : sfinae_base {

  // this may quietly fail:
  template<typename U> static yes& test(
      size_t (*n)[ sizeof( std::cout << * static_cast<U*>(0) ) ] );

  // "..." provides fallback in case above fails
  template<typename U> static no& test(...);

  static bool const value = sizeof( test<T>( NULL ) ) == sizeof( yes );
};
#包括
结构sfinae_基础{
typedef char yes[1];
typedef字符编号[2];
};
模板
结构具有插入运算符:sfinae\u base{
//这可能会悄然失败:
模板静态是&测试(

我应该更忠实地回答这个问题。 一个有效的实施方案是:

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> {
};
命名空间具有\u插入\u运算符\u impl{
typedef字符号;
typedef char yes[2];
构造任意{
模板任意_t(t常数&);
};

没有运算符这当然是可行的,但为什么?@Potatoswatter:为什么并不重要。请假设在我的项目的其余部分,我知道我在做什么。如果你必须知道,它是框架的一部分,用于传递任何类型的参数,以形成本地化错误消息的一部分。所有这些细节对于这个问题都是不必要的。如果你确定现在如何做,请回答这个问题。这将是非常感谢的。为什么总是很重要。它不会编译时出现几个错误。第一个错误是:没有依赖于模板参数的“test”参数,因此必须有一个“test”声明。顺便说一句:operatorBTW#2:ostream::ostream()是受保护的。@Paul:修补好了。我想到了“教人钓鱼”这句格言……如果你不能调试这些东西,解决它一次也不会真正帮助你。我已经用GCC 4.5.1()但是你要自己把它移植到4.2.1。如果我自己修复了它,那么任何读过你答案的人都会读到一个根本不起作用的答案。你真的想让你的非工作答案保持原样吗?我同意,它实际上不起作用。它只是利用重载解析+
操作符的契约
#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 );
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’
#include <iostream>

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

template<typename T>
struct has_insertion_operator : sfinae_base {

  // this may quietly fail:
  template<typename U> static yes& test(
      size_t (*n)[ sizeof( std::cout << * static_cast<U*>(0) ) ] );

  // "..." provides fallback in case above fails
  template<typename U> static no& test(...);

  static bool const value = sizeof( test<T>( NULL ) ) == sizeof( yes );
};
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> {
};