Я хочу иметь несколько перегруженных глобальных to_string ()
функций, которые принимают некоторый тип T
и преобразовать его в строковое представление. В общем случае я хочу написать:
template inline
typename enable_if::value
&& has_insertion_operator::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
struct has_insertion_operator : sfinae_base {
template static yes& test( U& );
template static no& test(...);
static std::ostream &s;
static T const &t;
static bool const value = sizeof( test( s << t ) ) == sizeof( yes ); // line 48
};
(Это заимствовано из this
и это .)
Кажется, это работает.
Но теперь я хочу иметь перегруженную версию to_string
для типов, у которых не есть operator , но действительно имеют свои собственные
to_string ()
member , то есть:
template inline
typename enable_if::value
&& has_to_string::value,
void>::type
to_string( T const &t, OutputStringType *out ) {
*out = t.to_string();
}
Реализация has_to_string
:
#define DECL_HAS_MEM_FN(FN_NAME) \
template \
struct has_##FN_NAME : sfinae_base { \
template struct type_check; \
template static yes& test(type_check*); \
template static no& test(...); \
static bool const value = sizeof( test(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::value’:
foo.cpp:104: instantiated from here
foo.cpp:48: error: no match for ‘operator<<’ in ‘has_insertion_operator::s << has_insertion_operator::t’
Похоже, что SFINAE не происходит. Как мне правильно написать has_insertion_operator
, чтобы он определял, доступен ли глобальный оператор ?
FYI: Я использую g ++ 4.2.1 (тот, который поставляется как часть Xcode в Mac OS X). Также хотелось бы, чтобы код был только стандартным C ++ 03 без сторонних библиотек, например Boost.
Спасибо!