使用 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
};
它借用了 这个
和这个。)
这似乎有效。
但现在我想要一个 to_string
的重载版本,用于那些没有有operator<<
但有的类型> 有自己的 to_string()
member 函数,即:
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 );
这部分看起来工作正常。它改编自<一href="https://stackoverflow.com/questions/257288/">这个。) 然而,当我:
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,没有第 3 方库,例如 Boost。
谢谢!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我应该更忠实于这个答案。
一个可行的实现是:
我相信它实际上并不依赖于 SFINAE。
I should have simply been more faithful to this answer.
A working implementation is:
I believe that it does not actually rely on SFINAE.
第 48 行
value
的初始值设定项不在 SFINAE 工作的上下文中。尝试将表达式移动到函数声明中。然而,我不得不质疑这件事的复杂程度。我看到非正交机制会相互冲突(
to_string
与operator<<
),并且我听到一些糟糕的假设被抛弃(例如运算符<<
是全局的,而不是成员,尽管在这方面实现的代码看起来不错)。The initializer of
value
on line 48 is not in a context where SFINAE works. Try moving the expression to the function declaration.However, I have to question the amount of sophistication that is going into this. I see non-orthogonal mechanisms that will grind against each other (
to_string
vs.operator<<
) and I hear poor assumptions getting tossed around (for example thatoperator<<
is global vs a member, although the code as implemented looks OK in that regard).