User-defined manipulators that accept arguments

D

Dave

Hello all,

It is my understanding that there is not a portable way to write a
user-defined manipulator that takes arguments. Please consider below which,
for purposes of illustration, implements a manipulator similar to setw().
Presumably, I have broken a rule here and this program is non-conforming.
However, I cannot see what rule that would be. May I request those who are
so inclined to try and poke holes in it?

Thank!
Dave


#include <iostream>
#include <ostream>
#include <string>

using namespace std;

template<typename T, typename C>
class ManipInfra
{
public:
ManipInfra(
basic_ostream<C> &(*pFun)(basic_ostream<C> &, T),
T val
): manipFun_(pFun), val_(val)
{
}

void operator()(basic_ostream<C> &os) const
{
manipFun_(os, val_);
}

private:
T val_;
basic_ostream<C> &(*manipFun_)(basic_ostream<C> &, T);
};

template<typename T, typename C>
basic_ostream<C> &operator<<(
basic_ostream<C> &os,
const ManipInfra<T, C> &manip
)
{
manip(os);

return os;
}

ostream &setTheWidth(ostream &os, int n)
{
os.width(n);

return os;
}

ManipInfra<int, char> setWidth(int n)
{
return ManipInfra<int, char>(setTheWidth, n);
}

int main()
{
cout << setWidth(10) << right << "foo" << endl;
}
 
A

Alf P. Steinbach

* Dave:
It is my understanding that there is not a portable way to write a
user-defined manipulator that takes arguments.

Where on Earth did you get that idea?

But it does seem to be difficult and perhaps impossible to provide
a solution that is both efficient and totally type-safe for arbitrary
argument type.

That is a general problem in C++.

Please consider below which,
for purposes of illustration, implements a manipulator similar to setw().
Presumably, I have broken a rule here and this program is non-conforming.

Yes, you use three spaces for indentation. That was just something I
suggested tongue-in-cheek in a meeting. And what do you know, suddenly
they all started using it, and now, years after, there seems to be no
way to stop 'em... :-(

Seriously, you have _inconsistent_ indentation.

That's Very Bad, although not a language rule violation.


[snip]
May I request those who are so inclined to try and poke holes in it?
OK.


#include <iostream>
#include <ostream>
#include <string>

using namespace std;

template<typename T, typename C>
class ManipInfra
{
public:
ManipInfra(
basic_ostream<C> &(*pFun)(basic_ostream<C> &, T),
T val
): manipFun_(pFun), val_(val)
{
}

Use typedefs.

You don't support non-copyable T objects.

For a generic ManipInfra class don't copy the T objects: pass by
reference to const, all the way (that means that the final iostream
manipulator function cannot be used as a standalone function, add a
comment to that effect).

void operator()(basic_ostream<C> &os) const
{
manipFun_(os, val_);
}

To support the client code return the stream object.
private:
T val_;
basic_ostream<C> &(*manipFun_)(basic_ostream<C> &, T);
};

template<typename T, typename C>
basic_ostream<C> &operator<<(
basic_ostream<C> &os,
const ManipInfra<T, C> &manip
)
{
manip(os);

return os;
}

E.g. this would be simplified.
 
D

Dave

Alf P. Steinbach said:
* Dave:

Where on Earth did you get that idea?

Josuttis, "The C++ Standard Library", page 613.

Thanks for the reply; I'll study it more tomorrow when my wits are about me!
 

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
474,470
Messages
2,571,807
Members
48,797
Latest member
PeterSimpson
Top