这已经被编辑了几次,我们决定调用包装集合的主类RangePrinter。
一旦您编写了一次性操作符<< overload,这将自动适用于任何集合,除非您将需要一个特殊的映射来打印对,并且可能希望在那里自定义分隔符。
您还可以在项目上使用特殊的“print”函数,而不是直接输出它,有点像STL算法允许您传入自定义谓词。对于map,您可以这样使用它,使用std::pair的自定义打印机。
您的“默认”打印机只会将其输出到流中。
好的,让我们用一台定制打印机。我将外层类改为RangePrinter。所以我们有两个迭代器和一些分隔符,但还没有定制如何打印实际的项。
struct DefaultPrinter
{
template< typename T >
std::ostream & operator()( std::ostream& os, const T& t ) const
{
return os << t;
}
// overload for std::pair
template< typename K, typename V >
std::ostream & operator()( std::ostream & os, std::pair<K,V> const& p)
{
return os << p.first << '=' << p.second;
}
};
// some prototypes
template< typename FwdIter, typename Printer > class RangePrinter;
template< typename FwdIter, typename Printer >
std::ostream & operator<<( std::ostream &,
RangePrinter<FwdIter, Printer> const& );
template< typename FwdIter, typename Printer=DefaultPrinter >
class RangePrinter
{
FwdIter begin;
FwdIter end;
std::string delim;
std::string open;
std::string close;
Printer printer;
friend std::ostream& operator<< <>( std::ostream&,
RangePrinter<FwdIter,Printer> const& );
public:
RangePrinter( FwdIter b, FwdIter e, Printer p,
std::string const& d, std::string const & o, std::string const& c )
: begin( b ), end( e ), printer( p ), open( o ), close( c )
{
}
// with no "printer" variable
RangePrinter( FwdIter b, FwdIter e,
std::string const& d, std::string const & o, std::string const& c )
: begin( b ), end( e ), open( o ), close( c )
{
}
};
template<typename FwdIter, typename Printer>
std::ostream& operator<<( std::ostream& os,
RangePrinter<FwdIter, Printer> const& range )
{
const Printer & printer = range.printer;
os << range.open;
FwdIter begin = range.begin, end = range.end;
// print the first item
if (begin == end)
{
return os << range.close;
}
printer( os, *begin );
// print the rest with delim as a prefix
for( ++begin; begin != end; ++begin )
{
os << range.delim;
printer( os, *begin );
}
return os << range.close;
}
现在,默认情况下,只要键和值类型都是可打印的,并且当它们都不是可打印的(就像任何其他类型一样),或者如果您不想要“=”作为分隔符,它就可以用于映射,并且您可以使用自己的特殊项目打印机。
现在,我将自由函数移到末尾来创建这些:
free-function(迭代器版本)看起来像这样,你甚至可以有默认值:
template<typename Collection>
RangePrinter<typename Collection::const_iterator> rangePrinter
( const Collection& coll, const char * delim=",",
const char * open="[", const char * close="]")
{
return RangePrinter< typename Collection::const_iterator >
( coll.begin(), coll.end(), delim, open, close );
}
然后你可以将它用于std::set by
std::cout << outputFormatter( mySet );
您还可以编写带有自定义打印机和带有两个迭代器的自由函数版本。在任何情况下,它们都将为您解析模板参数,并且您将能够将它们作为临时参数传递。