Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > How to print container elements which are pointers

Reply
Thread Tools

How to print container elements which are pointers

 
 
V.Subramanian, India
Guest
Posts: n/a
 
      11-09-2012
In the following program,
I have kept the data members ONLY for learning purpose.

#include <cstdlib>
#include <iostream>
#include <string>
#include <list>
#include <algorithm>

using namespace std;

class Person {

public:
explicit Person(const string& arg);
string name;
};

inline Person:erson(const string& arg) : name(arg)
{
}

class Club {

public:
list<Person*> officers;
};

class Print_name {

public:
Print_name(ostream& os);
void operator()(const Person* const & arg) const;

private:
ostream& out;
};

inline Print_name:rint_name(ostream& os) : out(os)
{
}

inline void Print_name:perator()(
const Person* const & arg) const
{
out << arg->name << endl;
}

int main()
{
Club c;

c.officers.push_back(new Person(string("one")));
c.officers.push_back(new Person(string("two")));
c.officers.push_back(new Person(string("three")));

for_each(c.officers.begin(),
c.officers.end(),
Print_name(cout));

return EXIT_SUCCESS;
}

The above program uses 'std::for_each()'
algorithm. The third argument to this
algorithm is a function object 'Print_name'.
The argument to the function object is the
output stream into which we want to write
the contents.

Since the container elements are pointers,
I am unable to use the 'std::copy()' algorithm
with ostream_iterator because the value
which will be passed to ostream_iterator
is a pointer.

something like:
copy(c.officers.begin(),
c.officers.end(),
ostream_iterator<Person*>(cout, "\n"));
This wil simply print the memory addresses
to the standard output. Am I correct ?

Is there a clean solution instead of the
'std::for_each()' algorithm with the
'Print_name' function object
combination which I have used in the
above program ?

Please provide the solution.

Is it possible to use the 'std::copy()' algorithm
for the above scenario ?

Thanks
V.Subramanian
India.
 
Reply With Quote
 
 
 
 
SG
Guest
Posts: n/a
 
      11-09-2012
On Nov 9, 3:36*am, "V.Subramanian, India" wrote:
> [...]
> Since the container elements are pointers,
> I am unable to use the 'std::copy()' algorithm
> with ostream_iterator because the value
> which will be passed to ostream_iterator
> is a pointer.
>
> something like:
> copy(c.officers.begin(),
> * * * * c.officers.end(),
> * * * * ostream_iterator<Person*>(cout, "\n"));
> This will simply print the memory addresses
> to the standard output. Am I correct ?


Yes. Unless you provide an overload that treats Person pointers
differently, like Luca suggested.

> Is there a clean solution instead of the
> 'std::for_each()' algorithm with the
> 'Print_name' function object
> combination which I have used in the
> above program ?
> [...]
> Is it possible to use the 'std::copy()' algorithm
> for the above scenario ?


Sure. There are lots of "clean" solutions. The easiest one is probably
the one using for-range:

for (auto& pp : c.officers) {
cout << pp->name << endl;
}

If you want to use std::copy with an ostream_iterator, you could use
boost::indirect_iterator

:::
ostream& operator<<(ostream& os, Person const& x);
:::

copy(boost::make_indirect_iterator(c.officers.begi n()),
boost::make_indirect_iterator(c.officers.end()),
ostream_iterator<Person>(cout));

if you don't like to overload operator<< for Person pointers.
 
Reply With Quote
 
 
 
 
Seungbeom Kim
Guest
Posts: n/a
 
      11-11-2012
On 2012-11-08 18:36, V.Subramanian, India wrote:
>
> Since the container elements are pointers,
> I am unable to use the 'std::copy()' algorithm
> with ostream_iterator because the value
> which will be passed to ostream_iterator
> is a pointer.
>
> something like:
> copy(c.officers.begin(),
> c.officers.end(),
> ostream_iterator<Person*>(cout, "\n"));
> This wil simply print the memory addresses
> to the standard output. Am I correct ?
>
> Is there a clean solution instead of the
> 'std::for_each()' algorithm with the
> 'Print_name' function object
> combination which I have used in the
> above program ?


If for some reason you don't want std::for_each and you don't
want an overloaded operator<<(ostream& o, const Person* p),
you can use std::transform to "transform" the pointers to objects
of a type designated for printing the names:

class Print_name {
const Person* person;
public:
Print_name(const Person* p) : person(p) { }
static Print_name create(const Person* p) { return Print_name(p); }
friend ostream& operator<<(std:stream& os, Print_name pn)
{ os << pn.person->name; }
};

std::transform(c.officers.begin(),
c.officers.end(),
std:stream_iterator<Print_name>(std::cout, "\n"),
Print_name::create);

You may want to avoid making a indirect function call to
Print_name::create for each Person pointer and inline the call to the
constructor by employing a class type:

class Print_name {
// ...
struct creator {
Print_name operator()(const Person* p) const
{ return Print_name(p); }
};
// ...
};

std::transform(c.officers.begin(),
c.officers.end(),
std:stream_iterator<Print_name>(std::cout, "\n"),
Print_name::creator());

This way, everything is inline, and the Print_name objects that get
passed around are only as big as a Person pointer, so the compiled
code can be very efficient.

--
Seungbeom Kim
 
Reply With Quote
 
Zhihao Yuan
Guest
Posts: n/a
 
      11-27-2012
On Thursday, November 8, 2012 8:36:30 PM UTC-6, V.Subramanian, India wrote:
> c.officers.push_back(new Person(string("one")));


To expose a pointer-based interface is very dangerous, since it's too
easy to leak a new-ed memory (your sample program already leaked) or
encounter a data corruption if you insist to delete the pointers
somewhere.

Anyway, here is my suggestion: to define a custom iterator.

First, as usual, you need an output operator for Person:

friend ostream& operator<<(ostream& out, Person const& p) {
out << p.name;
return out;
}

And then, a proxy-like iterator in Club:

class Club {

public:
struct iterator : list<Person>::iterator {
explicit iterator(list<Person*>::iterator i) : ptr_(i) {}

iterator(iterator const& i) : ptr_(i.ptr_) {}

iterator& operator=(iterator i) {
using std::swap;
swap(this->ptr_, i.ptr_);
return *this;
}

reference operator*() const {
return **ptr_;
}

pointer operator->() const {
return &(operator*());
}

iterator& operator++() {
++ptr_;
return *this;
}

iterator operator++(int) {
iterator tmp(*this);
++(*this);
return tmp;
}

/* operator-- omitted */

friend bool operator==(iterator x, iterator y) {
return x.ptr_ == y.ptr_;
}

friend bool operator!=(iterator x, iterator y) {
return !(x == y);
}

private:
list<Person*>::iterator ptr_;
};
list<Person*> officers;

iterator begin() {
return iterator(officers.begin());
}

iterator end() {
return iterator(officers.end());
}
};

So that you can use

copy(c.begin(),
c.end(),
ostream_iterator<Person>(cout, "\n"));

To print the Club. Cool?
 
Reply With Quote
 
Zhihao Yuan
Guest
Posts: n/a
 
      11-27-2012
Sorry, one important error.

On Monday, November 26, 2012 6:41:59 PM UTC-6, Zhihao Yuan wrote:
> struct iterator : list<Person>::iterator {


I extended an iterator for the typedefs, but got an base class
subobject unintentionally. Should be:

class Club {

typedef list<Person>::iterator _IterT;

public:
struct iterator : std::iterator<
_IterT::iterator_category,
_IterT::value_type,
_IterT::difference_type,
_IterT:ointer,
_IterT::reference
> {


Or just a list of public typedefs.

So sorry.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Copy elements from one STL container to another STL container Marko.Cain.23@gmail.com C++ 4 02-16-2006 05:03 PM
deleting all elements in a STL container of pointers edward.birch@gmail.com C++ 5 12-18-2005 11:50 PM
container elements for repeating elements ('element farms') needed? Wolfgang Lipp XML 1 01-30-2004 04:09 PM
Does deleting a container of pointers also delete the (contained) pointers? Xamalek C++ 7 11-04-2003 04:17 PM



Advertisments