C++ c++;boost::任何定义我自己的打印,
我一直在努力寻找如何使用C++ c++;boost::任何定义我自己的打印,,c++,boost-any,C++,Boost Any,我一直在努力寻找如何使用boost::any创建一个打印函数,该函数可以首先使用模板打印任何类型 template <typename T> struct printer { void print(ostream& os, const boost::any& a); }; 模板 结构打印机{ 无效打印(ostream&os,const boost::any&a); }; 我需要先定义print()。 我希望让真正的操作员查看Boost邮件列表上的此线程
boost::any
创建一个打印函数,该函数可以首先使用模板打印任何类型
template <typename T>
struct printer {
void print(ostream& os, const boost::any& a);
};
模板
结构打印机{
无效打印(ostream&os,const boost::any&a);
};
我需要先定义print()
。
我希望让真正的
操作员查看Boost邮件列表上的此线程:
它有一些想法,其中一些看起来还行,而另一些(对我来说)则不行。不过,总体而言,这似乎是一项很难以一般方式完成的任务,因为(如该线程中所述),某些类型永远不可能是ostream'able,但可以包含在boost::any
对象中。有一种非常简单的方法可以做到这一点,如“”:
struct拖缆{
虚拟无效打印(ostream&o,const boost::any&a)const=0;
虚拟拖缆*clone()常量=0;
虚拟~streamer(){}
};
模板
struct streamer\u impl:拖缆{
void print(ostream&o,const boost::any&a)const{o clone():0),o_(a.o_){
模板
any_out&运算符=(const T&r){
任何输出(r)。交换(*本);
归还*这个;
}
~any_out(){删除拖缆}
friend std::ostream&operator我这样做,我认为这样做既干净又安全:
任何_extension.hpp:
namespace cpputil
{
struct AnyWriter
{
/// Register a type with the AnyWriter.
/// @pre T must have an ostream << operator available somewhere
template<class T> static bool registerType()
{
return registeredTypes().emplace(std::type_index(typeid(T)),
std::bind(&AnyWriter::write<T>,
std::placeholders::_1,
std::placeholders::_2)).second;
}
/// Write any registred object to a stream
/// @pre Underlying type must have been registered with a call to AnyWriter::registerType<T>
/// @param os is reference to a std::ostream
/// @param anyObject is a reference to a boost::any
static void writeAny(std::ostream& os, const boost::any& anyObject);
private:
// A function object that converts an any to a type and streams it to an ostream
using WriteFunction = std::function<void (std::ostream&, const boost::any&)>;
// a map of typeinfo to WriteFunction
using RegisteredTypes = std::unordered_map<std::type_index, WriteFunction >;
// retrieve the WriteFunction map in a safe way
static RegisteredTypes& registeredTypes();
// Convert an any to a type, and write it to a stream
template<class T> static void write(std::ostream& os, const boost::any& anyObject) {
try {
const T& typedObject = boost::any_cast<const T&>(anyObject);
os << typedObject;
}
catch(boost::bad_any_cast& e) {
os << "<exception in conversion: " << e.what() << ">";
}
}
};
}
namespace std {
ostream& operator<<(ostream& os, const ::boost::any& anyObject);
}
名称空间cpputil
{
结构任意编写器
{
///向AnyWriter注册类型。
///@pre T必须有一个由Pawel Zubrycki(提到Björn Karlsson的书)给出的非常好的答案
但代码在以下几行中有一些错误:
// ...
o << *boost::any_cast<T>(a); // should be: o << *boost::any_cast<T>(&a);
// ...
a.streamer_->print(o, a); // should be: a.streamer_->print(o, a.o_);
如果我们将拖缆实例化为
new streamer_impl<T>()
…这是一个解决方案
另一种解决方案是保留引用并调整streamer\u impl
的模板实例化。请参见下文
以下推荐的解决方案是:
#ifndef ANY_OUT_H
#define ANY_OUT_H
#include <iostream>
#include <boost/any.hpp>
struct streamer {
virtual void print(std::ostream &o, const boost::any &a) const =0;
virtual streamer * clone() const = 0;
virtual ~streamer() {}
};
template <class T>
struct streamer_impl: streamer{
void print(std::ostream &o, const boost::any &a) const { o << boost::any_cast<T>(a); }
streamer *clone() const { return new streamer_impl<T>(); }
};
class any_out {
boost::any o_;
streamer *streamer_;
void swap(any_out & r){
std::swap(streamer_, r.streamer_);
std::swap(o_, r.o_);
}
public:
any_out(): streamer_(0) {}
template<class T> any_out(const T& value)
: o_(value),
#if 1
streamer_(new streamer_impl<typename std::decay<decltype(value)>::type>)
#else
streamer_((o_.type() == typeid(const char *))
? static_cast<streamer *>(new streamer_impl<const char *>)
: static_cast<streamer *>(new streamer_impl<T>))
#endif
{
}
// template<class T> any_out(const T value)
// : o_(value),
// streamer_(new streamer_impl<T>)
// {
// }
any_out(const any_out& a)
: o_(a.o_), streamer_(a.streamer_ ? a.streamer_->clone() : 0) {}
template <class T>
any_out & operator=(const T& r) {
any_out(r).swap(*this);
return *this;
}
~any_out() { delete streamer_; }
friend std::ostream &operator<<(std::ostream& o, const any_out & a);
};
std::ostream &operator<<(std::ostream& o, const any_out & a) {
if(a.streamer_)
a.streamer_->print(o, a.o_);
return o;
}
#endif
#如果有
#定义任何输出
#包括
#包括
结构拖缆{
虚拟无效打印(标准::ostream&o,常数boost::任意&a)常数=0;
虚拟拖缆*clone()常量=0;
虚拟~streamer(){}
};
模板
struct streamer\u impl:拖缆{
void print(std::ostream&o,const boost::any&a)const{o clone():0{}
模板
任意输出和运算符=(常数T&r){
任何输出(r)。交换(*本);
归还*这个;
}
~any_out(){删除拖缆}
friend std::ostream&Operator谢谢你给我寄来这个解决方案你太棒了,Karlsson先生(这本书的作者)太棒了。我刚刚想起他的书中有解决这个问题的方法。我很高兴我能帮上忙。
// ...
o << *boost::any_cast<T>(a); // should be: o << *boost::any_cast<T>(&a);
// ...
a.streamer_->print(o, a); // should be: a.streamer_->print(o, a.o_);
#ifndef ANY_OUT_H
#define ANY_OUT_H
#include <iostream>
#include <boost/any.hpp>
struct streamer {
virtual void print(std::ostream &o, const boost::any &a) const =0;
virtual streamer * clone() const = 0;
virtual ~streamer() {}
};
template <class T>
struct streamer_impl: streamer{
void print(std::ostream &o, const boost::any &a) const { o << *boost::any_cast<T>(&a); }
streamer *clone() const { return new streamer_impl<T>(); }
};
class any_out {
streamer *streamer_;
boost::any o_;
void swap(any_out & r){
std::swap(streamer_, r.streamer_);
std::swap(o_, r.o_);
}
public:
any_out(): streamer_(0) {}
template<class T> any_out(const T& value)
: streamer_(new streamer_impl<T>()), o_(value) {}
any_out(const any_out& a)
: streamer_(a.streamer_ ? a.streamer_->clone() : 0), o_(a.o_) {}
template <class T>
any_out & operator=(const T& r) {
any_out(r).swap(*this);
return *this;
}
~any_out() { delete streamer_; }
friend std::ostream &operator<<(std::ostream& o, const any_out & a);
};
std::ostream &operator<<(std::ostream& o, const any_out & a) {
if(a.streamer_)
a.streamer_->print(o, a.o_);
return o;
}
#endif
{
any_out a = 5;
std::cout << a << std::endl;
}
int main()
{
char str[] = "mystring";
any_out a = str;
std::cout << a << std::endl;
a = "myconststring";
std::cout << a << std::endl;
}
any_out(const T& value)
new streamer_impl<T>()
any_out(const T value)
#ifndef ANY_OUT_H
#define ANY_OUT_H
#include <iostream>
#include <boost/any.hpp>
struct streamer {
virtual void print(std::ostream &o, const boost::any &a) const =0;
virtual streamer * clone() const = 0;
virtual ~streamer() {}
};
template <class T>
struct streamer_impl: streamer{
void print(std::ostream &o, const boost::any &a) const { o << boost::any_cast<T>(a); }
streamer *clone() const { return new streamer_impl<T>(); }
};
class any_out {
boost::any o_;
streamer *streamer_;
void swap(any_out & r){
std::swap(streamer_, r.streamer_);
std::swap(o_, r.o_);
}
public:
any_out(): streamer_(0) {}
template<class T> any_out(const T& value)
: o_(value),
#if 1
streamer_(new streamer_impl<typename std::decay<decltype(value)>::type>)
#else
streamer_((o_.type() == typeid(const char *))
? static_cast<streamer *>(new streamer_impl<const char *>)
: static_cast<streamer *>(new streamer_impl<T>))
#endif
{
}
// template<class T> any_out(const T value)
// : o_(value),
// streamer_(new streamer_impl<T>)
// {
// }
any_out(const any_out& a)
: o_(a.o_), streamer_(a.streamer_ ? a.streamer_->clone() : 0) {}
template <class T>
any_out & operator=(const T& r) {
any_out(r).swap(*this);
return *this;
}
~any_out() { delete streamer_; }
friend std::ostream &operator<<(std::ostream& o, const any_out & a);
};
std::ostream &operator<<(std::ostream& o, const any_out & a) {
if(a.streamer_)
a.streamer_->print(o, a.o_);
return o;
}
#endif
int main()
{
char str[] = "mystring";
any_out a = str;
std::cout << a << std::endl;
a = "myconststring";
std::cout << a << std::endl;
}