我是初学者C ++开发人员,我对通过模板进行toString
和ostream
运算符集成有疑问。
我有这样的代码:
struct MethodCheckerTypes{
typedef unsigned char TrueType;
typedef long FalseType;
};
template<typename T>struct HasToString{
template<typename K>static typename MethodCheckerTypes::TrueType test(decltype(&K::toString));
template<typename> static typename MethodCheckerTypes::FalseType test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(typename MethodCheckerTypes::TrueType);
typedef decltype(test<T>(0)) ValueType;
};
template<typename T, typename K> struct IfDef{};
template<> struct IfDef<typename MethodCheckerTypes::TrueType, ostream&>{
typedef ostream& type;
};
class WithToString{
public:
string toString() const{
return "hello";
}
};
template<typename F, typename CharT, typename Traits> typename IfDef<typename HasToString<F>::ValueType, basic_ostream<CharT, Traits>&>::type operator<<(basic_ostream<CharT, Traits>& out, const F &ref){
out<<ref.toString().c_str();
return out;
}
int main(int argc, char **argv){
WithToString hasToString;
cout<<hasToString<<endl;
return 0;
}
代码已经过编译而没有错误,并且应用程序已成功执行。 使用这种方法好吗?我想在没有任何帮助的情况下实现它。
答案 0 :(得分:1)
实现operator<<
的方法本身是正常的。但是使用你不理解的部分语言是不好的做法(我不相信初学者可以编写这样的代码)。您有两种选择:实现toString
成员函数或重载operator<<(std::ostream&, T)
。后一种方法使您可以使用boost::lexical_cast
将对象转换为字符串。至于我,后一种方法更多的是C ++ ish,如果你能做一些没有成员函数的事情,最好这样做。
答案 1 :(得分:0)
我使用@Begemoth解决方案重载流运算符&lt;&lt;然后添加一个便利&#34; mixin&#34; class&#34; toString&#34;在需要立即字符串的情况下的方法,例如调试:
template<typename T>
class ToString
{
public:
std::string toString() const
{
return convertToString(static_cast<const T&>(*this));
}
};
template<typename T>
inline std::string convertToString(const T& value)
{
std::stringstream s;
s << value;
return s.str();
}
如果你有ostream运算符,你可以继承这个类,它会在你的类上给你一个toString方法。如果您正在使用boost,那么您可以使用lexical_cast替换convertToString的实现:
template<typename T>
inline std::string convertToString(const T& value)
{
return boost::lexical_cast<std::string>(value);
}
如果你的类是通过指针设计的继承和多态访问,那么上面的解决方案不会起作用,因为模板在编译时被绑定,所以需要采用不同的方法。可以使用以下mixin类代替&#34; ToString&#34;在上面定义虚拟方法的地方。然后提供便利宏以根据模板函数&#34; convertToString&#34;来实现虚拟功能。这必须添加到每个派生类的类主体中,因为它需要被覆盖并且&#34; this&#34;指针静态绑定到当前类型。
class ToStringVirtual
{
public:
virtual ~ToStringVirtual() {}
virtual std::string toString() const = 0;
};
#define IMPLEMENT_ToStringVirtual public: std::string toString() const override { return convertToString(*this); }