【发布时间】:2011-04-24 03:46:43
【问题描述】:
我想要几个重载的全局 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 用于不 有operator<< 但有 有自己的to_string() member em> 函数,即:
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();
}
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,以便确定全局operator<< 是否可用?
仅供参考:我使用的是 g++ 4.2.1(在 Mac OS X 上作为 Xcode 的一部分提供的版本)。 另外,我希望代码只是标准 C++03,没有第三方库,例如 Boost。
谢谢!
【问题讨论】:
-
这当然是可行的,但是为什么?
-
@Potatoswatter:为什么不重要。请假设对于我的项目的其余部分,我知道我在做什么。如果您必须知道,它是框架的一部分,用于传递任何类型的参数以形成本地化错误消息的一部分。这个问题不需要的所有细节。如果你知道怎么做,请回答这个问题。将不胜感激。
-
为什么总是重要的。