Quiero tener varias funciones globales to_string()
sobrecargadas que toman algún tipo T
y convertirlo a su representación de cadena. Para el caso general, quiero ser capaz de escribir:Usando SFINAE para verificar si hay operador global <<?
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();
}
Mi implementación de has_insertion_operator
hasta ahora es:
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
};
(Se toma prestado de this y this.) que parece funcionar . Pero ahora yo quiero tener una versión sobrecargada de to_string
para los tipos que hacer no tener operator<<
pero hacer tienen su propia to_string()
miembro de la función, es decir:
template<class T,class OutputStringType> inline
typename enable_if<!has_insertion_operator<T>::value
&& has_to_string<T,std::string (T::*)() const>::value,
void>::type
to_string(T const &t, OutputStringType *out) {
*out = t.to_string();
}
La implementación de has_to_string
es:
#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);
(Esta parte parece funcionar bien. Se ha adaptado de this.) Sin embargo, cuando tengo:
struct S {
string to_string() const {
return "42";
}
};
int main() {
string buf;
S s;
to_string(s, &buf); // line 104
}
me sale:
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’
Parece que SFINAE no está sucediendo. ¿Cómo escribo has_insertion_operator
correctamente para que determine si está disponible un operator<<
global?
FYI: Estoy usando g ++ 4.2.1 (el que se envía como parte de Xcode en Mac OS X). Además, me gustaría que el código sea solo C++ 03 estándar sin bibliotecas de terceros, por ejemplo, Boost.
Gracias!
Es todo posible, pero * ¿por qué? – Potatoswatter
@Potatoswatter: el por qué no es importante. Por favor, asuma que durante el resto de mi proyecto sé lo que estoy haciendo. Si debe saber, es parte del marco para pasar parámetros de cualquier tipo para formar parte de un mensaje de error localizado.Los detalles de todos los que son innecesarios para esta pregunta. Si sabe cómo hacerlo, responda la pregunta. Sería muy apreciado. –
Por qué siempre es importante. – GManNickG