std::copy 到 std::cout 以获得 std::pair
我有下一个代码:
#include <iostream>
#include <algorithm>
#include <map>
#include <iterator>
//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;
}
在这段代码中,我只想将映射复制到输出流。 为此,我需要定义运算符 <<(..) - 好的。 但根据名称查找规则编译器找不到我的运算符<<()。
因为 std::cout、std::pair 和 std::copy 调用了我的运算符<< - 全部来自命名空间 std。
快速解决方案 - 添加我的操作器<< 到 std 命名空间 - 但它很丑陋,恕我直言。
您知道该问题有哪些解决方案或解决方法?
I have next code:
#include <iostream>
#include <algorithm>
#include <map>
#include <iterator>
//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;
}
In this code I just want copy map to output stream. For do this I need define operator <<(..) - OK.
But according names finding rules compiler can't find my operator<<().
Because std::cout, std::pair and std::copy which called my operator<< - all from namespace std.
Quick solution - add my oerator<< to std namespace - but it is ugly, imho.
What solutions or workaround for this problem do you know?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
没有标准的方法来计算 std::pair ,因为,你想要的打印方式可能与下一个人想要的方式不同。 对于自定义函子或 lambda 函数来说,这是一个很好的用例。 然后,您可以将其作为参数传递给 std::for_each 来完成工作。
要从代码中调用此函子:
There is no standard way to cout a
std::pair
because, well, how you want it printed is probably different from the way the next guy wants it. This is a good use case for a custom functor or a lambda function. You can then pass that as an argument tostd::for_each
to do the work.To call this functor from your code:
我发明了一种新的优雅方法来解决这个问题。
在阅读答案时,我有很多有趣的想法:
>::first 和 std::pair< >::第二位成员;
我想我将来会使用所有这些想法来解决其他不同的问题。
但对于这种情况,我知道我可以将我的问题表述为“将映射的数据转换为字符串并将它们写入输出流”而不是“将映射的数据复制到输出流”。 我的解决方案如下:
我认为这种方法比其他方法最简短且最具表现力。
I've founded one new elegant way to solve this problem.
I've got many interest ideas when read answers:
I think I will use all of this ideas in future for solve different other problems.
But for this case I've understaded that I can formulate my bproblem as "transform map's data to strings and write them to output stream" instead "copy map's data to ouput stream". My solution looks like:
I think this method is most short and expressive than others.
我只想指出,根据 C++ 标准,向 std:: 命名空间添加内容是非法的(请参阅第 17.4.3.1 节)。
I'd just like to point out that adding things to the std:: namespace is illegal according to the C++ Standard (see section 17.4.3.1).
你想要的是一个转换迭代器。 这种迭代器包装了另一个迭代器,转发了operator++、operator==等所有定位方法,但是重新定义了operator*和operator->。
快速草图:
What you want is a transforming iterator. This kind of iterator wraps another iterator, forwards all positioning methods like operator++ and operator==, but redefines operator* and operator->.
Quick sketch :
只是路过,但这对我来说完成了工作,所以对其他人也可以(剪切版本):
给出的用例:
Just passing by, but this did the job for me, so it can for somebody else (cut version):
Use case given:
使用 Boost Lambda,你可以尝试这样的事情。 我的 Boost Lambda 版本实际上不起作用,我稍后会测试并修复。
Using Boost Lambda, you could try something like this. The version I have of Boost Lambda, this doesn't actually work, I'll test and fix later.
[我宁愿删除这个答案,但我会暂时保留它,以防有人觉得讨论有趣。]
由于它是 std 库的合理扩展,我只是将它放在 std 命名空间中,特别是如果这是一次性的事情。 如果其他人在其他地方做同样的事情,您可以将其声明为静态,以防止它导致链接器错误。我想到的另一个解决方案是为 std::pair 创建一个包装器:
[I'd rather delete this answer, but I'll leave it for now, in case someone finds the discussion interesting.]
Since it's a reasonable extension to the std library, I'd just put it in std namespace, especially if this is a one time thing. You can just declare it static to prevent it from causing linker errors, should someone else do the same thing someplace else.Another solution that comes to mind is to create a wrapper for std::pair:
更加简单通用!
more simple and universal !
这是一个与
std::copy
和std::ostream_iterator
一起使用的std::pair
类型的适配器。 您最终会保留一个额外的引用,但编译器优化可能会处理它。 顺便说一句,std::map::value_type
的std::pair
中的第一个类型将是const
。Here is an adaptor to use with
std::copy
andstd::ostream_iterator
for thestd::pair
type. You end up holding one extra reference, but the compiler optimization may take care of it. BTW, the first type instd::pair
of thestd::map::value_type
will be aconst
.--- 用C++11就可以了
--- It is fine with C++11