473,403 Members | 2,270 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,403 software developers and data experts.

insertion operator and namespace?


Dear all,

I have some problem with insertion operator together with namespace.
I have a header file foo.h containing declaration of classes, typedefs and
insertion operators for the typedefs in a named namespace

namespace foo
{

class Foo
{
typedef std::vector<unsigned char> Vec;
typedef std::vector<Key> VecVec;
....

};

std::ostream & operator<<(std::ostream &os, const Foo::Vec &v);
std::ostream & operator<<(std::ostream &os, const Foo::VecVec &v);

}

Then the definition in the file foo.cc

namespace foo
{

std::ostream & operator<<(std::ostream &os, const Foo::Vec &v)
{
...
}
std::ostream & operator<<(std::ostream &os, const Foo::VecVec &v)
{
}

}

Now I would like to use the insertion operators in a programm. If the
program looks like

#include "foo.h"

int main()
{
Foo::Vec vec;
Foo::VecVec vecs;

....

// "using namespace" directive required
// otherwise compiler get confused with
// other available insertions in std::
{
using namespace foo;
std::cout << vec << std::endl;
std::cout << vecs << std::endl;
}
}

I wonder how to avoid using the using namespace directive?

Sincerely,

Patrick
Nov 8 '05 #1
20 3819
On Tue, 8 Nov 2005 21:40:47 +0100, Patrick Guio <pa******@ii.uib.no>
wrote:

Dear all,

I have some problem with insertion operator together with namespace.
I have a header file foo.h containing declaration of classes, typedefs and
insertion operators for the typedefs in a named namespace

namespace foo
{

class Foo
{
typedef std::vector<unsigned char> Vec;
typedef std::vector<Key> VecVec;
....

};

std::ostream & operator<<(std::ostream &os, const Foo::Vec &v);
std::ostream & operator<<(std::ostream &os, const Foo::VecVec &v);

}

Then the definition in the file foo.cc

namespace foo
{

std::ostream & operator<<(std::ostream &os, const Foo::Vec &v)
{
...
}
std::ostream & operator<<(std::ostream &os, const Foo::VecVec &v)
{
}

}

Now I would like to use the insertion operators in a programm. If the
program looks like

#include "foo.h"

int main()
{
Foo::Vec vec;
Foo::VecVec vecs;

....

// "using namespace" directive required
// otherwise compiler get confused with
// other available insertions in std::
{
using namespace foo;
std::cout << vec << std::endl;
std::cout << vecs << std::endl;
}
}

I wonder how to avoid using the using namespace directive?

You have to put the overloads for operator<< into the global
namespace, i.e.:

std::ostream & operator<<(std::ostream &os
, const foo::Foo::Vec &v)
{
...
}
std::ostream & operator<<(std::ostream &os
, const foo::Foo::VecVec &v)
{
}

What I don't understand is why your earlier declarations compile
without specifying the namespace, i.e.:
#include "foo.h"

int main()
{
Foo::Vec vec;
Foo::VecVec vecs;


This shouldn't compile without a using directive, a using declaration,
or specifying the namespace qualifier explicitly.

--
Bob Hairgrove
No**********@Home.com
Nov 8 '05 #2
> #include "foo.h"

int main()
{
Foo::Vec vec;
Foo::VecVec vecs;
how does that compile? class Foo is defined inside a namespace foo in
foo.h, which is not part of the current namespace?

....

// "using namespace" directive required
// otherwise compiler get confused with
// other available insertions in std::
{
using namespace foo;
std::cout << vec << std::endl;
std::cout << vecs << std::endl;
}

}


using the << operator overload for you types requires
argument-dependend lookup because the concerning operator is not
defined in a visible namespace. unfortunately the standard doesn't seem
to define argument-dependend lookup for typedefs, the lookup is still
associated to the concrete type (std::vector in your case).

you could call the operator directly to be able to specify the
namespace explicitely, though you probably wouldn't want to do that:

(foo::operator << (std::cout, vec)) << std::endl;
(foo::operator << (std::cout, vecs)) << std::endl;

maybe you should just define the operator overloads in the global
namespace.

-- peter

Nov 8 '05 #3
On Tue, 8 Nov 2005, Bob Hairgrove wrote:

Hi Bob,

I still have problem which can be summarize in the following code:
You have to put the overloads for operator<< into the global
namespace, i.e.:

std::ostream & operator<<(std::ostream &os
, const foo::Foo::Vec &v)
{
...
}
std::ostream & operator<<(std::ostream &os
, const foo::Foo::VecVec &v)
{
}

What I don't understand is why your earlier declarations compile
without specifying the namespace, i.e.:
#include "foo.h"

int main()
{
Foo::Vec vec;
Foo::VecVec vecs;


This shouldn't compile without a using directive, a using declaration,
or specifying the namespace qualifier explicitly.


My fault, this is just a code snippet I made to sketch my problem. Of
course there should foo::Foo::Vec and foo::Foo::VecVec (or a
"using foo::Foo" directive before).

Anyway I still have 2 compilation problems in the following code with
the class Fred in namespace fred.
The compiler (g++ v.4.0.1) complains that
* 'int fred::Fred::i_' is private within the context 'return o << fred.i_;'
* 'std::cout << [snip] << fred << "\n";' is an ambiguous overload
and candidates are:
std::ostream& operator<<(std::ostream&, const fred::Fred&)
std::ostream& fred::operator<<(std::ostream&, const fred::Fred&)

Any idea of how to solve these problems?

Sincerely,

Patrick
#include <iostream>

// class in fred namespace
namespace fred
{
class Fred
{
public:
friend std::ostream& operator<< (std::ostream& o, const fred::Fred& fred);
Fred() : i_(1) {}
~Fred() {}
private:
int i_;
};
}

std::ostream& operator<< (std::ostream& o, const fred::Fred& fred)
{
return o << fred.i_;
}

int main()
{
fred::Fred fred;
std::cout << "My Fred object: " << fred << "\n";
return 0;
}

Nov 9 '05 #4
Patrick Guio wrote:
Anyway I still have 2 compilation problems in the following code with
the class Fred in namespace fred.
The compiler (g++ v.4.0.1) complains that
* 'int fred::Fred::i_' is private within the context 'return o << fred.i_;'
* 'std::cout << [snip] << fred << "\n";' is an ambiguous overload
and candidates are:
std::ostream& operator<<(std::ostream&, const fred::Fred&)
std::ostream& fred::operator<<(std::ostream&, const fred::Fred&)

Any idea of how to solve these problems?

Sincerely,

Patrick
#include <iostream>

// class in fred namespace
namespace fred
{
class Fred
{
public:
friend std::ostream& operator<< (std::ostream& o, const fred::Fred& fred);
This operator's name is actually fred::operator<<().
Fred() : i_(1) {}
~Fred() {}
private:
int i_;
};
}

std::ostream& operator<< (std::ostream& o, const fred::Fred& fred)
And this one is

std::ostream ::operator<<().

Just put the operator in the namespace.
{
return o << fred.i_;
Here you get an error because this operator is not a friend. This
functions is not the same as the one declared as friend in Fred.
}

int main()
{
fred::Fred fred;
std::cout << "My Fred object: " << fred << "\n";
return 0;
}

Jonathan

Nov 9 '05 #5
On Wed, 9 Nov 2005, Jonathan Mcdougall wrote:

Hi Jonathan,

Thank you for your answer. I still wonder whether the following code
snippet could be simplified?
Sincerely, Patrick

namespace foo
{
class Foo
{
public:
typedef std::vector<unsigned char> Vec;
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f);
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo::Vec & v);
Foo() : a(3, 5) {};
~Foo() {};
private:
Vec a;
};
}

std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
{
return os << f.a << std::endl;
}

// insertion operator used by the insertion operator
// std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
std::ostream & foo::operator<<(std::ostream &os, const foo::Foo::Vec & v)
{
using foo::Foo;
// code for insertion operator of a std::vector
Foo::Vec::const_iterator i = v.begin(), e = v.end();
// code for insertion operator of a std::vector
.....
}

// insertion operator for object as in the main:
// foo::Foo::Vec a(4, 1);
// std::cout << a << std::endl;
std::ostream & operator<<(std::ostream &os, const foo::Foo::Vec & v)
{
return foo::operator<<(os , v);
}
int main()
{
foo::Foo f;
std::cout << f << std::endl;

foo::Foo::Vec a(4, 1);
std::cout << a << std::endl;
}

Nov 9 '05 #6
On Wed, 9 Nov 2005, Patrick Guio wrote:

Hi Jonathan,

Maybe I should formulate my question differently. Do I need both insertion
operators (in global and foo namespace) for type foo::Foo::Vec so that it
can be used for private member object of class Foo and also in global
namespace? Can that be simplified to one insertion operator?
Sincerely,
Patrick

Thank you for your answer. I still wonder whether the following code snippet
could be simplified?
Sincerely, Patrick

namespace foo
{
class Foo
{
public:
typedef std::vector<unsigned char> Vec;
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f);
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo::Vec & v);
Foo() : a(3, 5) {};
~Foo() {};
private:
Vec a;
};
}

std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
{
return os << f.a << std::endl;
}

// insertion operator used by the insertion operator
// std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
std::ostream & foo::operator<<(std::ostream &os, const foo::Foo::Vec & v)
{
using foo::Foo;
// code for insertion operator of a std::vector
Foo::Vec::const_iterator i = v.begin(), e = v.end();
// code for insertion operator of a std::vector
....
}

// insertion operator for object as in the main:
// foo::Foo::Vec a(4, 1);
// std::cout << a << std::endl;
std::ostream & operator<<(std::ostream &os, const foo::Foo::Vec & v)
{
return foo::operator<<(os , v);
}

int main()
{
foo::Foo f;
std::cout << f << std::endl;

foo::Foo::Vec a(4, 1);
std::cout << a << std::endl;
}


--
Patrick Guio
Para//ab, Bergen Centre for Computational Science
Thormøhlensgt. 55, N-5008 Bergen, Norway
Tel : +47 55584361 - Fax: +47 55584295
Mail: echo cn**********@oppf.hvo.ab | perl -pe 'y/a-z/n-za-m/'
URL : http://www.bccs.uib.no
Nov 10 '05 #7
On Thu, 10 Nov 2005 07:23:15 +0100, Patrick Guio <pa******@ii.uib.no>
wrote:
Can that be simplified to one insertion operator?


Yes ... please refer to my previous post.

--
Bob Hairgrove
No**********@Home.com
Nov 10 '05 #8
On Thu, 10 Nov 2005, Bob Hairgrove wrote:
On Thu, 10 Nov 2005 07:23:15 +0100, Patrick Guio <pa******@ii.uib.no>
wrote:
Can that be simplified to one insertion operator?


Yes ... please refer to my previous post.


Hi Bob,

I tried to put the insertion operator (declarartion and definitions) in
the global namespace as you mentionned

std::ostream & operator<<(std::ostream &o, const foo::Foo & v);
std::ostream & operator<<(std::ostream &o, const foo::Foo::Vec & v);

but then the insertion operator for foo::Foo is not a friend function of
the class Foo any longer. and the compiler complains about privacy-

But if I put both insertions inside

namespace foo
{
class Foo
{
public:
typedef std::vector<unsigned char> Vec;
// insertion operator for foo::Foo call insertion operator for foo::Foo::Vec
friend std::ostream & operator<<(std::ostream &o, const Foo & f);
friend std::ostream & operator<<(std::ostream &o, const Vec & v);
private:
Vec a;
};
}

Then the compiler stop complaining about privacy but I cannot use the
insertion for an object in the global namespace of type foo::Foo::Vec
because it does not find the correct insertion.

I tried to only move the insertion operator for foo::Foo::Vec in the
global namespace but it didn't help either, the compiler complain that it
does not find the correct insertion for foo::Foo::Vec in the insertion
foo::Foo.

When fixing insertion for foo::Foo::Vec in global namespace, it creates
trouble for insertion for foo::Foo::Vec in the insertion of foo::Foo and
vice-versa.

Any idea?

Sincerely,

Patrick
Nov 10 '05 #9
On Thu, 10 Nov 2005 20:31:05 +0100, Patrick Guio <pa******@ii.uib.no>
wrote:
Hi Bob,

I tried to put the insertion operator (declarartion and definitions) in
the global namespace as you mentionned

std::ostream & operator<<(std::ostream &o, const foo::Foo & v);
std::ostream & operator<<(std::ostream &o, const foo::Foo::Vec & v);

but then the insertion operator for foo::Foo is not a friend function of
the class Foo any longer. and the compiler complains about privacy-


Try this:

namespace foo {
class Foo {
friend std::ostream & ::operator<<(std::ostream &o, const Foo & v);
/* ...etc. */
};
} // namespace foo

Note the "::" in front of "operator".

--
Bob Hairgrove
No**********@Home.com
Nov 10 '05 #10
On Thu, 10 Nov 2005, Bob Hairgrove wrote:
On Thu, 10 Nov 2005 20:31:05 +0100, Patrick Guio <pa******@ii.uib.no>
wrote:
Hi Bob,

I tried to put the insertion operator (declarartion and definitions) in
the global namespace as you mentionned

std::ostream & operator<<(std::ostream &o, const foo::Foo & v);
std::ostream & operator<<(std::ostream &o, const foo::Foo::Vec & v);

but then the insertion operator for foo::Foo is not a friend function of
the class Foo any longer. and the compiler complains about privacy-


Try this:

namespace foo {
class Foo {
friend std::ostream & ::operator<<(std::ostream &o, const Foo & v);
/* ...etc. */
};
} // namespace foo

Note the "::" in front of "operator".


Hi Bob,

Then I get an error message that the "global scope has no
"operator<<"" with Intel compiler "icpc -ansi" (v.8.1) and
that "insertion operator should have been declared inside '::' for
declaration and "not in a namespace surrounding '::'" for the definition
with g++ (v.4.0.1).

Sincerely,

Patrick
Nov 10 '05 #11
Patrick Guio wrote:
On Wed, 9 Nov 2005, Patrick Guio wrote:

Hi Jonathan,
Thank you for your answer. I still wonder whether the following code snippet
could be simplified?
Please, don't top-post.
Maybe I should formulate my question differently. Do I need both insertion
operators (in global and foo namespace) for type foo::Foo::Vec so that it
can be used for private member object of class Foo and also in global
namespace? Can that be simplified to one insertion operator?


You have several problems here.

1) you cannot do something like

std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
{
return os << f.a << std::endl;
}

to define an operator in namespace foo. You have to put the definition
inside the namespace:

namespace foo
{
std::ostream & operator<<(std::ostream &os, const foo::Foo & f)
{
return os << f.a << std::endl;
}
}

and drop the foo:: qualifier

2) an operator for foo::Foo::Vec will not be found if it is in a
namespace because Vec is a typedef for std::vector. That means

foo::Foo::Vec v;
std::cout << v;

will only search the enclosing namespace (global if you are in main(),
for example) and std::. This is because ADL only applies to the real
type of an object.

3) as soon as an operator is defined, and can be found, you don't need
to define more for the same type. Actually, if you do, you'll get an
ambiguity error.
namespace foo
{
class Foo
{
public:
typedef std::vector<unsigned char> Vec;
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f);
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo::Vec & v);
Forget these. Define a public print() member function that does the
job:

void print(std::ostream &out) const
{
// output informations to out, manually output the std::vector
}
Foo() : a(3, 5) {};
~Foo() {};
private:
Vec a;
};
}

std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
{
Here, call f.print().
return os << f.a << std::endl;
}

// insertion operator used by the insertion operator
// std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
std::ostream & foo::operator<<(std::ostream &os, const foo::Foo::Vec & v)
{
using foo::Foo;
// code for insertion operator of a std::vector
Foo::Vec::const_iterator i = v.begin(), e = v.end();
// code for insertion operator of a std::vector
....
}
This operator won't be used outside namespace foo (if you don't dump it
with "using namespace foo") because, as I said, Vec is a typedef.
// insertion operator for object as in the main:
// foo::Foo::Vec a(4, 1);
// std::cout << a << std::endl;
std::ostream & operator<<(std::ostream &os, const foo::Foo::Vec & v)
{
return foo::operator<<(os , v);
}
Drop this one, it is misleading. On first look, it seems like you are
defining an operator for the user defined type Vec, but this is an
operator for a std::vector<unsigned char>. It may cause ambiguity if
this is in a header and I include it. Either output the vector manually
in Foo::print() (as I did), or make this a named function (such as
output_vector()) in namespace foo.
int main()
{
foo::Foo f;
std::cout << f << std::endl;

foo::Foo::Vec a(4, 1);
std::cout << a << std::endl;
}


What you want is:

# include <vector>
# include <iostream>

namespace foo
{
class Foo
{
public:
typedef std::vector<unsigned char> Vec;

void print(std::ostream &out) const
{
out << "This is a Foo";
for (Vec::const_iterator itor = v.begin(); itor!=v.end(); ++itor)
{
out << *itor;
}
}

private:
Vec v;
};

std::ostream &operator<<(std::ostream &out, const Foo &f)
{
f.print(out);
return out;
}
}

int main()
{
foo::Foo f;
std::cout << f;
}
Jonathan

Nov 10 '05 #12

Bob Hairgrove wrote:
On Thu, 10 Nov 2005 20:31:05 +0100, Patrick Guio <pa******@ii.uib.no>
wrote:
Hi Bob,

I tried to put the insertion operator (declarartion and definitions) in
the global namespace as you mentionned

std::ostream & operator<<(std::ostream &o, const foo::Foo & v);
std::ostream & operator<<(std::ostream &o, const foo::Foo::Vec & v);

but then the insertion operator for foo::Foo is not a friend function of
the class Foo any longer. and the compiler complains about privacy-


Try this:

namespace foo {
class Foo {
friend std::ostream & ::operator<<(std::ostream &o, const Foo & v);
/* ...etc. */
};
} // namespace foo

Note the "::" in front of "operator".


This cannot work because if you qualify a friend declaration, the class
name must be declared before in that scope.
Jonathan

Nov 10 '05 #13
On Thu, 10 Nov 2005, Jonathan Mcdougall wrote:
Please, don't top-post.
Oops sorry, but what does top-post mean?
2) an operator for foo::Foo::Vec will not be found if it is in a
namespace because Vec is a typedef for std::vector. That means

foo::Foo::Vec v;
std::cout << v;

will only search the enclosing namespace (global if you are in main(),
for example) and std::. This is because ADL only applies to the real
type of an object.
It will work though with a "using namespace foo" directive (as you also
mention below in your mail) but that's exactly what I want to avoid.
3) as soon as an operator is defined, and can be found, you don't need
to define more for the same type. Actually, if you do, you'll get an
ambiguity error.
I Understand but is there any default stream insertion operator for
std::vector container? I thought there was not.
namespace foo
{
class Foo
{
public:
typedef std::vector<unsigned char> Vec;
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f);
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo::Vec & v);
Forget these. Define a public print() member function that does the
job:


I Understand, it is a good way to handle "printing" for class inheritance
as well.

void print(std::ostream &out) const
{
// output informations to out, manually output the std::vector
}
[snip]

std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
{ Here, call f.print(). } // insertion operator for object as in the main:
// foo::Foo::Vec a(4, 1);
// std::cout << a << std::endl;
std::ostream & operator<<(std::ostream &os, const foo::Foo::Vec & v)
{
return foo::operator<<(os , v);
}


Drop this one, it is misleading. On first look, it seems like you are
defining an operator for the user defined type Vec, but this is an
operator for a std::vector<unsigned char>. It may cause ambiguity if
this is in a header and I include it. Either output the vector manually
in Foo::print() (as I did), or make this a named function (such as
output_vector()) in namespace foo.


But that means writing the same code twice? Once for the private member
of type foo::Foo::Vec and once for any foo::Foo::Vec in global
(or any other) namespace ?
What you want is:

# include <vector>
# include <iostream>

namespace foo
{
class Foo
{
public:
typedef std::vector<unsigned char> Vec;

void print(std::ostream &out) const
{
out << "This is a Foo";
for (Vec::const_iterator itor = v.begin(); itor!=v.end(); ++itor)
{
out << *itor;
}
}
private:
Vec v;
};

std::ostream &operator<<(std::ostream &out, const Foo &f)
{
f.print(out);
return out;
}
}

int main()
{
foo::Foo f;
std::cout << f;
How handle in addition?

foo::Foo::Vec v(5, 1);
std::cout << v;
// or output_vector(v); ?
}
Isn't there a way to avoid code duplication of
for (Vec::const_iterator itor = v.begin(); itor!=v.end(); ++itor)
{
out << *itor;
}

So that it could be used to output object of type foo::Foo::Vec and
outputting the private member of type foo::Foo::Vec?

If I define a class foo::Foo::Vec that inherits std::vector<unsigned char>
instead of using typedef would that help?
Is using typedef's inside a class a good design?

Sincerely,

Patrick

Nov 11 '05 #14
Patrick Guio wrote:
On Thu, 10 Nov 2005, Jonathan Mcdougall wrote:
Please, don't top-post.
Oops sorry, but what does top-post mean?


http://en.wikipedia.org/wiki/Top-posting

Actually, the problem wasn't top posting, but lack of quoting. Google
groups added a "Show quoted text" at the bottom of your message, but it
was empty, sorry.
2) an operator for foo::Foo::Vec will not be found if it is in a
namespace because Vec is a typedef for std::vector. That means

foo::Foo::Vec v;
std::cout << v;

will only search the enclosing namespace (global if you are in main(),
for example) and std::. This is because ADL only applies to the real
type of an object.


It will work though with a "using namespace foo" directive (as you also
mention below in your mail) but that's exactly what I want to avoid.


Yes. The thing is, when I do for example

namespace test
{
typedef std::complex<double> my_complex;

void f()
{
my_complex c;
std::cout << c;
}
}

I expect the compiler to keep searching in namespace std, not in
namespace test. Obviously, the compiler cannot take in account every
namespace in which a typedef was used (you could typedef another
typedef which was in another namespace), so it only works with the
underlying type.
3) as soon as an operator is defined, and can be found, you don't need
to define more for the same type. Actually, if you do, you'll get an
ambiguity error.


I Understand but is there any default stream insertion operator for
std::vector container? I thought there was not.


There is not. Usually, you won't want to output a vector plainly on the
screen, you want to format it, to integrate it on something. That's why
none was defined: what would it do?
namespace foo
{
class Foo
{
public:
typedef std::vector<unsigned char> Vec;
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f);
friend std::ostream & foo::operator<<(std::ostream &os, const foo::Foo::Vec & v);


Forget these. Define a public print() member function that does the
job:


I Understand, it is a good way to handle "printing" for class inheritance
as well.


Yes, print() could be virtual for example.

void print(std::ostream &out) const
{
// output informations to out, manually output the std::vector
}


[snip]

std::ostream & foo::operator<<(std::ostream &os, const foo::Foo & f)
{

Here, call f.print().
} // insertion operator for object as in the main:
// foo::Foo::Vec a(4, 1);
// std::cout << a << std::endl;
std::ostream & operator<<(std::ostream &os, const foo::Foo::Vec & v)
{
return foo::operator<<(os , v);
}


Drop this one, it is misleading. On first look, it seems like you are
defining an operator for the user defined type Vec, but this is an
operator for a std::vector<unsigned char>. It may cause ambiguity if
this is in a header and I include it. Either output the vector manually
in Foo::print() (as I did), or make this a named function (such as
output_vector()) in namespace foo.


But that means writing the same code twice? Once for the private member
of type foo::Foo::Vec and once for any foo::Foo::Vec in global
(or any other) namespace ?


If Vec is meant to be used both inside and outside the class, make a
named free function to output it.

// in header
# include <vector>
# include <ostream>

namespace foo
{
class Foo
{
public:
typedef std::vector<int> Vec;

void print(std::ostream &out) const;

private:
Vec v_;
};

void output_vector(std::ostream &out, const Foo::Vec &v);
std::ostream &operator<<(std::ostream &out, const Foo &f);

} // namespace foo
// in impl file
# include "header"

namespace foo
{

void Foo::print(std::ostream &out) const
{
// print Foo related things

output_vector(out, v_);
}

void output_vector(std::ostream &out, const Foo::Vec &v)
{
// output v
}

std::ostream &operator<<(std::ostream &out, const Foo &f)
{
f.print(out);
}

} // namespace foo

Is using typedef's inside a class a good design?


Yes.
Jonathan

Nov 11 '05 #15
On Fri, 11 Nov 2005, Jonathan Mcdougall wrote:

Hi Jonathan,
3) as soon as an operator is defined, and can be found, you don't need
to define more for the same type. Actually, if you do, you'll get an
ambiguity error.
I Understand but is there any default stream insertion operator for
std::vector container? I thought there was not.


There is not. Usually, you won't want to output a vector plainly on the
screen, you want to format it, to integrate it on something. That's why
none was defined: what would it do?


Exactly, that was also my understanding.
If Vec is meant to be used both inside and outside the class, make a
named free function to output it.
As an alternative to a free function one could also define a
manipulator struct/class of Foo::Key with a global std::ostream insertion
operator like:
// in header
# include <vector>
# include <ostream>

namespace foo
{
class Foo
{
public:
typedef std::vector<int> Vec;

void print(std::ostream &out) const;

private:
Vec v_;
};

// void output_vector(std::ostream &out, const Foo::Vec &v);
struct output_vector
{
output_vector(const Foo::Vec & v);
Foo::Vec _v;
};

std::ostream &operator<<(std::ostream &out, const Foo::Vec &v);
std::ostream &operator<<(std::ostream &out, const Foo &f);

} // namespace foo
// in impl file
# include "header"

namespace foo
{

void Foo::print(std::ostream &out) const
{
// print Foo related things

//output_vector(out, v_);
out << output_vector(v_);
}

// void output_vector(std::ostream &out, const Foo::Vec &v)
// {
// output v
// }
output_vector::output_vector(const Foo::Vec & v) :: _v(v) {}

std::ostream &operator<<(std::ostream &oot, const Foo::Vec &v)
{
// output v
}

std::ostream &operator<<(std::ostream &out, const Foo &f)
{
// f.print(out);
}

} // namespace foo

That way it is still possible to have a Foo::Vec in chained insertion.

Any idea if this a good design?
Is using typedef's inside a class a good design?


Yes.


Good to know!

Cheers,

Patrick

Nov 11 '05 #16
Patrick Guio wrote:
On Fri, 11 Nov 2005, Jonathan Mcdougall wrote:
If Vec is meant to be used both inside and outside the class, make a
named free function to output it.
As an alternative to a free function one could also define a
manipulator struct/class of Foo::Key with a global std::ostream insertion
operator like:

struct output_vector
{
output_vector(const Foo::Vec & v);
Foo::Vec _v;


You want a reference here. And don't start names with an underscore, it
is reserved for the implemententation. If you want to denote
membership, some people prefix the names with m_ or suffix it with _
and some people like having an unadorned name.
};

std::ostream &operator<<(std::ostream &out, const Foo::Vec &v);

void Foo::print(std::ostream &out) const
{
out << output_vector(v_);
}

output_vector::output_vector(const Foo::Vec & v) :: _v(v) {}

std::ostream &operator<<(std::ostream &oot, const Foo::Vec &v)
{
// output v
}
But now you will need an operator<< which takes a const output_vector&.
The Foo::Vec version is unused.
That way it is still possible to have a Foo::Vec in chained insertion.
Any idea if this a good design?


What's good depends on the situation. If you think you can handle it,
it simplifies the code and is easy to maintain, go for it.
Jonathan

Nov 11 '05 #17
On Fri, 11 Nov 2005, Jonathan Mcdougall wrote:

Hi Jonathan,
If Vec is meant to be used both inside and outside the class, make a
named free function to output it.
As an alternative to a free function one could also define a
manipulator struct/class of Foo::Key with a global std::ostream insertion
operator like:

struct output_vector
{
output_vector(const Foo::Vec & v);
Foo::Vec _v;


You want a reference here. And don't start names with an underscore, it
is reserved for the implemententation. If you want to denote
membership, some people prefix the names with m_ or suffix it with _
and some people like having an unadorned name.


Good to know.
};

// std::ostream &operator<<(std::ostream &out, const Foo::Vec &v);
std::ostream &operator<<(std::ostream &out, const output_vector & v);

void Foo::print(std::ostream &out) const
{
out << output_vector(v_);
}

output_vector::output_vector(const Foo::Vec & v) :: _v(v) {}

// std::ostream &operator<<(std::ostream &oot, const Foo::Vec &v) std::ostream &operator<<(std::ostream &out, const output_vector & v) {
// output v
}
But now you will need an operator<< which takes a const output_vector&.
The Foo::Vec version is unused.


Oops, typo... But that's what I meant
That way it is still possible to have a Foo::Vec in chained insertion.
Any idea if this a good design?


What's good depends on the situation. If you think you can handle it,
it simplifies the code and is easy to maintain, go for it.


Thank you for this discussion, it was very helpful!
I have now made output_vector a template structure
(output_vector<vector_type>) and defined corresponding template insertion
operators and it works like a charm.

I extend my question to input insertion operator. Is this input method
a good design? Following is the sketch

Cheers,
Patrick

// declaration file
namespace foo
{

template <typename vector_type>
struct input_vector
{
input_vector() {}
vector_type m_vector;
};

template<typename vector_type>
std::istringstream & operator>>(std::istringstream & is, input_vector<vector_type> &v);
// following arespecialisation definitions
std::istringstream & operator>>(std::istringstream & is, input_vector<Foo::Vec> &k);
....
}

// definition file
namespace foo
{
std::istringstream & operator>>(std::istringstream & is, input_vector<Foo::Vec> &k)
{
// input from memory
}
}

Then I can insert

int main()
{
std::istringstream is("1,2,3,4,5");
foo::input_vector<foo::Foo::Vec> iv;
is >> iv;
foo::Foo::Vec V(iv.m_vector);
}
Nov 22 '05 #18
Patrick Guio wrote:
I extend my question to input insertion operator. Is this input method
a good design? Following is the sketch

// declaration file
namespace foo
{
template <typename vector_type>
struct input_vector
{
input_vector() {}
vector_type m_vector;
};

template<typename vector_type>
std::istringstream & operator>>(std::istringstream & is, input_vector<vector_type> &v);

// following arespecialisation definitions
std::istringstream & operator>>(std::istringstream & is, input_vector<Foo::Vec> &k);
....
}

// definition file
namespace foo
{
std::istringstream & operator>>(std::istringstream & is, input_vector<Foo::Vec> &k)
{
// input from memory
}
}

Then I can insert

int main()
{
std::istringstream is("1,2,3,4,5");
foo::input_vector<foo::Foo::Vec> iv;
is >> iv;
foo::Foo::Vec V(iv.m_vector);
}


Just want to make sure I understand: is input_vector a wrapper around
standard container classes to define input for them? If yes, I think
you are trying to make things a bit too much generic here.

Will input_vector be used in different contexts? If yes, are you sure
(or does it make sense) that the input will always have the same
format? Wouldn't it be better if you let the class itself interpret the
input?

If not, if you are searching for a more generic way to handle input and
store it in a collection, I think you should go for named functions, or
a class if you need a state. Something like

namespace parser
{
template <class Cont>
istream &comma_separated(std::istream &i, Cont &c);

template <class Cont>
istream &space_separated(std::istream &i, Cont &c);

template <class Cont>
istream &line_separated(std::istream &i, Cont &c);
}

class Test1
{
public:
void f(std::istream &i)
{
// Test1 expects space separated values
parser::space_separated(i, v_);
}

private:
std::vector<int> v_;
};

class Test2
{
public:
void f(std::istream &i)
{
// Test2 expects values on different lines
parser::line_separated(i, v_);
}

private:
std::vector<int> v_;
};

You could specialize parser functions a bit more, but still keeping
them low-level, and use them as building blocks in each class.

Still, these are wild guesses because you haven't said a word on your
"design".
Jonathan

Nov 22 '05 #19
On Mon, 14 Nov 2005, Jonathan Mcdougall wrote:

Hi Jonathan,

// declaration file
namespace foo
{
template <typename vector_type>
struct input_vector
{
input_vector() {}
vector_type m_vector;
};

template<typename vector_type>
std::istringstream & operator>>(std::istringstream & is, input_vector<vector_type> &v);

// following arespecialisation definitions
std::istringstream & operator>>(std::istringstream & is, input_vector<Foo::Vec> &k);
....
}

// definition file
namespace foo
{
std::istringstream & operator>>(std::istringstream & is, input_vector<Foo::Vec> &k)
{
// input from memory
}
}

Then I can insert

int main()
{
std::istringstream is("1,2,3,4,5");
foo::input_vector<foo::Foo::Vec> iv;
is >> iv;
foo::Foo::Vec V(iv.m_vector);
}
Just want to make sure I understand: is input_vector a wrapper around
standard container classes to define input for them? If yes, I think
you are trying to make things a bit too much generic here.


Basically yes it is a wrapper around standard container std::vector with
different "native" types (unsigned char, unsigned short and unsigned
long) but also std::vector< std::vector<native types>> that represent
encryption keys/keys collection.
Will input_vector be used in different contexts? If yes, are you sure
(or does it make sense) that the input will always have the same
format? Wouldn't it be better if you let the class itself interpret the
input?
Yes it might be used in different contexts in the sense that the input
may have different formats. As you wrote below, there might be
different separator.
I want to be able to input/import/set keys of different type to be used
in the encryption engine class for testing/benchmarking.

If not, if you are searching for a more generic way to handle input and
store it in a collection, I think you should go for named functions, or
a class if you need a state. Something like
I am not sure to understand What do you mean by a state?
namespace parser
{
template <class Cont>
istream &comma_separated(std::istream &i, Cont &c);

template <class Cont>
istream &space_separated(std::istream &i, Cont &c);

template <class Cont>
istream &line_separated(std::istream &i, Cont &c);
}


Wouldn't it make sense to define a structure
template<typename vec_type>
struct input_vec
{
// default is no separator
input_vec(const std::string sep=std::string()) : sep_(sep) {}
vec_type vec_;
std::string sep_;
};

and then have a single stream insertion operator for struct input_vec that
would use the member input_vec::sep_ ?

template <typename vec:type>
std::istream & operator>>(std::istream & is, input_vec<vec_type> & v);

istream cin;
input_vec<Vec> in(",");
cin >> in;
Vec v(in.vec_);

Or perhaps better use a single class for input_vec and output_vec with
different constructors?

Also if I want to have both insertion operator for std::istream and
std::istringstream, do I need to actually have 2 sets of
definition/declaration for each of them?

Sincerely,

Patrick

Nov 22 '05 #20
Patrick Guio wrote:
On Mon, 14 Nov 2005, Jonathan Mcdougall wrote:

Hi Jonathan,

// declaration file
namespace foo
{
template <typename vector_type>
struct input_vector
{
input_vector() {}
vector_type m_vector;
};

template<typename vector_type>
std::istringstream & operator>>(std::istringstream & is, input_vector<vector_type> &v);

// following arespecialisation definitions
std::istringstream & operator>>(std::istringstream & is, input_vector<Foo::Vec> &k);
....
}

// definition file
namespace foo
{
std::istringstream & operator>>(std::istringstream & is, input_vector<Foo::Vec> &k)
{
// input from memory
}
}

Then I can insert

int main()
{
std::istringstream is("1,2,3,4,5");
foo::input_vector<foo::Foo::Vec> iv;
is >> iv;
foo::Foo::Vec V(iv.m_vector);
}
Just want to make sure I understand: is input_vector a wrapper around
standard container classes to define input for them? If yes, I think
you are trying to make things a bit too much generic here.


Basically yes it is a wrapper around standard container std::vector with
different "native" types (unsigned char, unsigned short and unsigned
long) but also std::vector< std::vector<native types>> that represent
encryption keys/keys collection.
Will input_vector be used in different contexts? If yes, are you sure
(or does it make sense) that the input will always have the same
format? Wouldn't it be better if you let the class itself interpret the
input?


Yes it might be used in different contexts in the sense that the input
may have different formats. As you wrote below, there might be
different separator.
I want to be able to input/import/set keys of different type to be used
in the encryption engine class for testing/benchmarking.
If not, if you are searching for a more generic way to handle input and
store it in a collection, I think you should go for named functions, or
a class if you need a state. Something like


I am not sure to understand What do you mean by a state?


A object may have a state (member variables), but a namespace cannot
(well it can, but with namespace-global variables). This means you can
have two instances of a class (two objects), and by changing their
values, the member functions called on them will produce different
results. So if you need the parser to have a state, you need a class
and one (a stateful singleton) or several objects. If you don't, you
either need a stateless singleton (all-statics class) or simple free
functions in a namespace.
namespace parser
{
template <class Cont>
istream &comma_separated(std::istream &i, Cont &c);

template <class Cont>
istream &space_separated(std::istream &i, Cont &c);

template <class Cont>
istream &line_separated(std::istream &i, Cont &c);
}


Wouldn't it make sense to define a structure
template<typename vec_type>
struct input_vec
{
// default is no separator
input_vec(const std::string sep=std::string()) : sep_(sep) {}
vec_type vec_;
std::string sep_;
};

and then have a single stream insertion operator for struct input_vec that
would use the member input_vec::sep_ ?


Oh well these were just examples and my examples are always scrap. I
never was a good teacher.

namespace parser
{
template <class C>
istream &separated_by_something(std::istream &i, C &c, const
std::string &sep="\n");

template <class C>
istream &fixed_size(std::istream &i, C &c, std::size_t size);

template <class C, class Decoder>
istream &encrypted_fixed_size(std::istream &i, C &c, Decoder &d,
std:size_t size);
}

You know, something like that. But if, in your case, they can all be
factored in one function (or a class), go for it.
template <typename vec:type>
std::istream & operator>>(std::istream & is, input_vec<vec_type> & v);

istream cin;
input_vec<Vec> in(",");
cin >> in;
Vec v(in.vec_);

Or perhaps better use a single class for input_vec and output_vec with
different constructors?
You need to understand here that was is "better" for me will not
necessarily be "better" for you. I don't know what you have to do, I
don't understand exactly what you need. You are asking a kind of
question that is very hard to answer: a "is this good design" question.
Answering this kind of question over the net, without knowing anything
about your job, is very difficult.

[I am not telling you to stop asking questions, I am saying getting a
definite answer will be very difficult to obtain.]

Now, depending on what you want or need, and depending on the size of
the classes and also depending of the logic involved in reading and
writing, you may want to separate these two classes. If the code is
small, and it makes sense to bundle input and output together, go for
it. If you find yourself trying to manage a mammoth class which does
two completly unrelated things, you should separate them.

Normally, operators << and >> are used when the receiver does not need
to be parametrized. Something like

input_vec<Vec> in(",");
cin >> in;

is not common in my opinion (but I may be wrong). Usually, you
parametrize the stream, not the object. When the output or input
depends on the state of an object, I usually use member functions:

input_vec<Vec> in;
in.read_from(std::cin, ",");

or a user-defined stream

my_stream s(std::cin, ",");
input_vec<Vec> v;
s >> v;

You don't usually "prepare" the object to be streamed, because you want
to separate the state from the input/output.

// wrong (IMO)
input_vec<Vec> in;
in.separator(",");
in.encryption(..);
in.bla();
std::cin >> in;

But that's getting a matter of taste more than anything. Since
input_vec is only a wrapper, it could make sense, I don't know. I just
feel it doesn't look "right". Here's what I would do, based on what I
understand:
class C;

class key_input
{
public:
key_input(std::istream &in, const std::string &sep)
: in_(in), sep_(sep)
{
}

friend std::istream &operator>>(key_input &key, C &c)
{
// read from in_ depending on sep_ and possibly other parameters
// put values in c
}

private:
std::istream &in_;
std::string sep_;
};

class C
{
public:
typedef std::vector<whatever> Container;
Container cont;
};

std::istream &operator>>(std::istream &in, C &c)
{
// read some general values into c (such as the number of keys, a
date or something)

// delegate to key_input, the separator may be defined elsewhere,
such as in C
key_input kin(in, ",");
kin >> c;

return in;
}

int main()
{
C c;
std::cin >> c;
}

So that's just a matter of
1) separating input/output from the class
2) having different functions (be they operators or not) to do
different jobs

Modularity, one function, one responsability, you know, the usual talk.
Also if I want to have both insertion operator for std::istream and
std::istringstream, do I need to actually have 2 sets of
definition/declaration for each of them?


No, std::[i/o]stringstream is derived from std::[i/o]stream, so passing
by reference will be ok. Actually, to be more generic, you could pass
basic_istream and basic_ostream around and add template parameters for
the character type.

Hope this helps,
Jonathan

Nov 22 '05 #21

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Xavier Decoret | last post by:
The following code does not compoile with gcc-3.2.3 namespace dummy { //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Interface of Foo...
2
by: ryan.fairchild | last post by:
I have a problem I am trying to create a MyInt class to hanlde very large ints. Its for a class, therefore I can only do what the teach tells me. I want to be able to overload the insertion...
8
by: bipod.rafique | last post by:
Hello All, I need your help in understanding something. I have a simple class class test{ };
6
by: jack | last post by:
I have a class which overloads the insertion operator '<<' for every type that ostream handles. I do this so that I can use my class a direct replacement for cout and cerr where the insertion...
4
by: Raider | last post by:
Is there std::map member-function that do as code below? typedef std::map<NameClass, ValueClass> ParameterContainer; .... // this code is equivalent to "_Parameters = Value", // but a bit...
2
by: B. Williams | last post by:
I have an assignment for school to Overload the operators << and >and I have written the code, but I have a problem with the insertion string function. I can't get it to recognize the second of...
5
by: Naveen | last post by:
I am trying to write a conatiner which has std::map like methods but preserves the order of insertion. TO achieve this I thought of providing my own function for comparing the keys of the map....
5
by: phiefer3 | last post by:
I'm currently a student, but this problem isn't directly related to what I have to do on an assignment. It's just a problem I've had with some supporting features. First of all, I'm using MSVS...
3
by: kvnsmnsn | last post by:
I've been asked to overload the insertion operator. What exactly is the insertion operator in C++, and how would one overload it? I think that in C I could overload the "+" operator like so: ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.