当前位置:  开发笔记 > 编程语言 > 正文

std :: copy到std :: cout的std :: cout

如何解决《std::copy到std::cout的std::cout》经验,为你挑选了4个好方法。

我有下一个代码:

#include 
#include 
#include 
#include 

//namespace std
//{

std::ostream& operator << ( std::ostream& out, 
                const std::pair< size_t, size_t >& rhs )
{
    out << rhs.first << ", " << rhs.second;
    return out;
}
//}

int main() 
{

    std::map < size_t, size_t > some_map;

    // fill  some_map with random values
    for ( size_t i = 0; i < 10; ++i )
    {
        some_map[ rand() % 10 ] = rand() % 100;
    }

    // now I want to output this map
    std::copy( 
        some_map.begin(), 
        some_map.end(), 
        std::ostream_iterator< 
              std::pair< size_t, size_t > >( std::cout, "\n" ) );

    return 0;
}

在这段代码中我只想要复制映射到输出流.为此,我需要定义operator <<(..) - OK.但根据名称查找规则编译器找不到我的运算符<<().
因为std :: cout,std :: pair和std :: copy调用了我的运算符<< - all from namespace std.

快速解决方案 - 将我的oerator <<添加到std命名空间 - 但它很难看,imho.

您知道这个问题的解决方案或解决方法吗?



1> Michael Kris..:

cout a没有标准的方法,std::pair因为,你想要它的打印方式可能与下一个人想要它的方式不同.这是自定义函子或lambda函数的一个很好的用例.然后,您可以将其作为参数传递std::for_each给工作.

typedef std::map MyMap;

template 
struct PrintMyMap : public std::unary_function
{
    std::ostream& os;
    PrintMyMap(std::ostream& strm) : os(strm) {}

    void operator()(const T& elem) const
    {
        os << elem.first << ", " << elem.second << "\n";
    }
}

要从您的代码中调用此仿函数:

std::for_each(some_map.begin(),
              some_map.end(),
              PrintMyMap(std::cout));



2> bayda..:

我已经找到了一种解决这个问题的新方法.
阅读答案时,我有很多有趣的想法:

包装迭代器,用于将std :: pair转换为std :: string;

wrap std :: pair,有机会重载operator <<(...);

使用通常的std :: for_each和print functor;

将std :: for_each与boost :: labda一起使用 - 看起来不错,除了访问std :: pair <> :: first和std :: pair <> :: second members;

我想我将来会用这些想法来解决其他不同的问题.
但是对于这种情况,我已经明白我可以将我的问题表述为"将地图的数据转换为字符串并将其写入输出流"而不是"将地图的数据复制到输出流".我的解决方案如下:

namespace
{
std::string toString( const std::pair< size_t, size_t >& data)
{
    std::ostringstream str;
    str << data.first << ", " << data.second;
    return str.str();
}
} // namespace anonymous

std::transform( 
    some_map.begin(), 
    some_map.end(), 
    std::ostream_iterator< std::string >( std::cout, "\n" ),
    toString );

我认为这种方法比其他方法更短,更具表现力.



3> 小智..:

我只想指出,根据C++标准,将内容添加到std :: namespace是非法的(参见第17.4.3.1节).



4> MSalters..:

你想要的是一个转换迭代器.这种迭代器包装另一个迭代器,转发所有定位方法,如operator ++和operator ==,但重新定义operator*和operator->.

快速草图:

template  
struct transformingIterator : private ITER {
    transformingIterator(ITER const& base) : ITER(base) {}
    transformingIterator& operator++() { ITER::operator++(); return *this; }
    std::string operator*() const
    {
        ITER::value_type const& v = ITER::operator*();
        return "[" + v->first +", " + v->second + "]";
    }
...

推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有