Re: ostream_iterator for map
On Sat, 14 Apr 2012 11:24:34 -0700 (PDT)
Daniel Kr?gler <daniel.kruegler@googlemail.com> wrote:
the need for finding a matching name for operator<< is within
a member function of an instantiation of std::ostream_iterator.
.....
At the point where this member function is defined, your global
operator<< overload cannot be found
Thanks Daniel. I think I get it. My operator<< is in the global
namespace. When invoked in main(), its definition appears prior to
invocation. The compiler sees
A @ B
and starts by checking the global namespace for operator@ because that
is the context in which the operator is invoked.
The trick, then, is to make sure definition preceeds invocation, right?
If I define my overloaded operator<< way up at the top of main.C,
before #include <algorithm>, would it then be found? More
conventionally does,
#include <iostream>
#include <map>
#include "smooth_operator.h"
#include <iterator>
#include <algorithm>
meet the compiler's needs in a defined way?
I'm not aware of any prohibition against defining user code before
including library headers. It's a headache to manage in a large
project, but it seems otherwise OK to me.
One last option. I think I can use still use std::copy if I don't
use std::ostream_iterator.
Sure, sure, you can use std::copy as well in *this* specific example,
because I designed my pair_io to be implicitly convertible from the
source type.
Yes, I see. I tried something else that worked. I defined my own
iterator, see below. As I wrote it, thoughts occurred to me:
1. Maybe ostream doesn't define operator<< for std::pair because
pair, like all composite types and unlike scalar types, has no single
universal format.
2. Perhaps my iterator should take a functor to handle the actual
formatting.
3. Perhaps I should use std::transform to convert the pair to a string,
and use ostream_iterator<string>.
4. Oh. I've done that before.
Regarding efficiency, I concur with your point about a wrapper class. I
would argue that converting to string is also very efficient,
especially for a std::pair whose members are small. If the pair is:
pair<size_t, CAD_DRAWING>
yours is clearly the better approach!
What do you think about #2, though?
I would like to see ostream_iterator<std::pair<K,V>> defined in the
library, and I would like to be about to override the format on
a per-use basis, choosing among multiple formats for a given K,V type
pair. I see advantages to being able to influence the formating of
scalar types, too, but the lack of built-in support for streaming out
maps is an impediment to their use.
I think you will say the mechanism you presented meets my needs too,
and I agree. OTOH restricting ostream_iterator to use only operator<<
seems unnecessary, and more flexible iterators would make the standard
algorithms more, er, flexible.
Below is my iterator. The Oracles on StackOverflow say it's best not
to inherit from iterator. I was unable to determine why not.
template< typename T,
typename charT=char,
typename traits=char_traits<charT> >
class map_ostream_iterator
{
ostream &os;
const charT *delim;
public:
typedef output_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
map_ostream_iterator(std::ostream& os, charT *delim = "")
: os(os), delim(delim) {}
map_ostream_iterator<T,charT>& operator ++ () { return *this; }
map_ostream_iterator<T,charT> operator * () { return *this; }
void operator= (const T &val) { os << val << delim; }
};
Regards,
--jkl
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]