std::副本std::状性病::对
-
10-07-2019 - |
题
我有一个代号:
#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::状况、性传染疾病::对和std::副本,其中要求我的操作者<< -所有的名字空间的标准。
快速的解决方案-加入我的oerator<< std名字空间-但是这是丑陋的,恕我直言。
什么样的解决方案或解决这个问题你知道吗?
解决方案 2
我已经成立一个新的优雅的方式来解决这个问题。
我已经得到了许多感兴趣的想法的时候读的答案:
- 包迭代,对于改变性病::对性病::string;
- 包std::对,对有机会操作人员超载<<(...);
- 使用通常的标准::for_each与印函;
- 使用标准::for_each有提升::labda-看起来不错,除了访问以std::对< >::第一和性传播疾病::对< >::第二个成员;
我想我会使用所有这些想法在今后为解决不同的其他问题。
但是,对于这种情况下,我understaded我能制定我的bproblem为"变换地图的数据串而将它们写入到输出流"而不是"复制地图的数据的输出流"。我的解决方法看起来像:
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 );
我认为这种方法是最短和表现的比其他人。
其他提示
没有标准的方法来宣传std::pair
因为,你希望它打印的方式可能与下一个人想要它的方式不同。这是自定义函子或lambda函数的一个很好的用例。然后,您可以将其作为参数传递给std::for_each
来完成工作。
typedef std::map<size_t, size_t> MyMap;
template <class T>
struct PrintMyMap : public std::unary_function<T, void>
{
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<MyMap::value_type>(std::cout));
我只想指出,根据C ++标准,将内容添加到std :: namespace是非法的(参见第17.4.3.1节)。
你想要的是一个转换迭代器。这种迭代器包装另一个迭代器,转发所有定位方法,如operator ++和operator ==,但重新定义operator *和operator - <!> gt;。
快速草图:
template <typename ITER>
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 + "]";
}
...
刚刚路过,但这对我来说很合适,所以对其他人来说(剪切版):
template<typename First, typename Second>
struct first_of {
First& operator()(std::pair<First, Second>& v) const {
return v.first;
}
};
用例:
transform (v.begin (), v.end (),
ostream_iterator<int>(cout, "\n"), first_of<int, string> ());
使用Boost Lambda,你可以试试这样的东西。我有Boost Lambda的版本,这实际上没有用,我稍后会测试和修复。
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
std::for_each( some_map.begin(), some_map.end(),
std::cout << bind( &std::map<size_t,size_t>::value_type::first, _1 )
<< ","
<< bind( &std::map<size_t,size_t>::value_type::second, _1 ) );
[我宁愿删除这个答案,但我现在暂时离开,以防有人发现讨论有趣。]
因为它是对std库的合理扩展,所以我只是把它放在std命名空间中,特别是如果这是一次性的话。您可以将其声明为静态以防止它导致链接器错误,如果其他人在其他地方执行相同的操作。
另一个想到的解决方案是为std :: pair创建一个包装器:
template<class A, class B>
struct pairWrapper {
const std::pair<A,B> & x;
pairWrapper(const std::pair<A,B> & x) : x(x) {}
}
template<class A,class B>
std::ostream & operator<<(std::ostream & stream, const pairWrapper<A,B> & pw) { ... }
for (const auto& your_pair : your_container)
your_stream << "[" << your_pair.first << "," << your_pair.second << "]" << endl;
更简单,更普遍! for_each(some_map.begin(), some_map.end(), [](const std::map < size_t, size_t >::value_type &ite){
cout<<ite.first<<" "<<ite.second<<endl;
});
--- C ++ 11很好用