for_each algorithm and ostream

S

subramanian100in

I want to write data stored in a container into standard output or an
output file using for_each algorithm. To acheive this, the following
program creates a function object of type 'Print'. The argument to the
'Print' class ctor is an ostream object. This function object is
passed as the third argument to 'for_each' algorithm. The overloaded
function call operator in the 'Print' class, writes the data passed to
it into the ostream member data of the function object.

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

class Print
{
public:
explicit Print(ostream& arg);
template <typename T> bool operator()(const T& arg);

private:
ostream& os;
};

Print::print(ostream& arg) : os(arg)
{
}

template <typename T> inline bool Print::eek:perator()(const T& arg)
{
os << arg << endl;
return true;
}

int main()
{
typedef vector<int> Container;
Container c;

for (int i = 0; i != 10; ++i)
c.push_back(i);

for_each(c.begin(), c.end(), Print(cout));

ofstream ofs("Descending_order");

if (!ofs)
{
cout << "Could not create output file" << endl;
return EXIT_FAILURE;
}

for_each(c.rbegin(), c.rend(), Print(ofs));

return EXIT_SUCCESS;
}

This program works as expected. Is this approach of passing a function
object argument to for_each algorithm for printing the container data,
correct ? Kindly reply me if there is a better/cleaner solution and
please provide the same.

Thanks
V.Subramanian
 
S

Saeed Amrollahi

I want to write data stored in a container into standard output or an
output file using for_each algorithm. To acheive this, the following
program creates a function object of type 'Print'. The argument to the
'Print' class ctor is an ostream object. This function object is
passed as the third argument to 'for_each' algorithm. The overloaded
function call operator in the 'Print' class, writes the data passed to
it into the ostream member data of the function object.

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

class Print
{
public:
explicit Print(ostream& arg);
template <typename T> bool operator()(const T& arg);

Your function object is not predicate. A predicate is a function
object
(or a function) that returns a bool. for example find_if or count_if
need to
a predicate. but for for_each, what the return value does? So you can
use:
template said:
private:
ostream& os;

};

Print::print(ostream& arg) : os(arg)
{

}

template <typename T> inline bool Print::eek:perator()(const T& arg)
{
        os << arg << endl;
        return true;

What the value of return true statement?
}

int main()
{
        typedef vector<int> Container;
        Container c;

        for (int i = 0; i != 10; ++i)
                c.push_back(i);

        for_each(c.begin(), c.end(), Print(cout));

        ofstream ofs("Descending_order");

        if (!ofs)
        {
                cout << "Could not create output file" << endl;
                return EXIT_FAILURE;
        }

        for_each(c.rbegin(), c.rend(), Print(ofs));

        return EXIT_SUCCESS;

}

This program works as expected. Is this approach of passing a function
object argument to for_each algorithm for printing the container data,
correct ? Kindly reply me if there is a better/cleaner solution and
please provide the same.

Thanks
V.Subramanian

I think using ostream& data member is inevitable, but you can do the
same thing
using copy and ostream_iterator better and cleaner:
std::copy(c.begin(), c.end(), std::eek:stream_iterator<int>(cout,
"\n")); // put to cout
std::copy(c.rbegin(), c.rend(), std::eek:stream_iterator<int>(ofs,
"\n")); // put to ofs

Indeed, Bjarne Stroustrup wrote in Special edition (section 18.5.1):
In general, before using for_each(), consider if there is a more
specialized algorithm
that would do more for you.

Regards,
-- Saeed Amrollahi
 
J

James Kanze

I want to write data stored in a container into standard
output or an output file using for_each algorithm. To acheive
this, the following program creates a function object of type
'Print'. The argument to the 'Print' class ctor is an ostream
object. This function object is passed as the third argument
to 'for_each' algorithm. The overloaded function call operator
in the 'Print' class, writes the data passed to it into the
ostream member data of the function object.
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Print
{
public:
explicit Print(ostream& arg);
template <typename T> bool operator()(const T& arg);
private:
ostream& os;
};
Print::print(ostream& arg) : os(arg)
{
}
template <typename T> inline bool Print::eek:perator()(const T& arg)
{
os << arg << endl;
return true;
}
int main()
{
typedef vector<int> Container;
Container c;
for (int i = 0; i != 10; ++i)
c.push_back(i);
for_each(c.begin(), c.end(), Print(cout));
ofstream ofs("Descending_order");
if (!ofs)
{
cout << "Could not create output file" << endl;
return EXIT_FAILURE;
}
for_each(c.rbegin(), c.rend(), Print(ofs));
return EXIT_SUCCESS;
}
This program works as expected. Is this approach of passing a
function object argument to for_each algorithm for printing
the container data, correct ?

Yes, but...
Kindly reply me if there is a better/cleaner solution and
please provide the same.

You're actually copying, so you should be using std::copy, with
a specialized output iterator. In this case, the specialized
output iterator already exists: std::eek:stream_iterator.
Otherwise, I'd say that it's more "idiomatic" in some sense to
define a new output iterator, and use it, but that has to be
weighed against the fact that writing an iterator is
considerably more complicated than writing a simple functional
object. (It shouldn't be, of course, but the STL idiom tends to
make things more difficult than they should be.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top