namespace trouble

  • Thread starter Bruno de Oliveira Schneider
  • Start date
B

Bruno de Oliveira Schneider

Hello all,

I'm rewriting a C++ framework, so that old prefixed names are replaced
by namespaces. Please consider the following class:

=== boundingbox.h ===
[...]
namespace VART {
class Transform; // forward declaration of class Transform
class BoundingBox {
friend std::eek:stream& operator<<(std::eek:stream& output, const
BoundingBox& box);
public:
[...]
void Transform(const Transform& trans);
[...]
===============
1) I tried "class VART::Transform;" before "namespace VART {" which
gave me compile errors. Is the current declaration ok? Is there a
better way?

2) The output operator is inside namespace VART. Could it be outside?
Users of this framework would fell more confortable if it was...

3) I get "boundingbox.h:36: error: declaration of 'void
VART::BoundingBox::Transform(const VART::Transform&)' transform.h:24:
error: changes meaning of 'Transform' from 'class VART::Transform'"
when compiling on g++. I don't see why VART::BoundingBox::Transform
conflicts with VART::Transform. What could be done here?
 
V

Victor Bazarov

Bruno said:
Hello all,

I'm rewriting a C++ framework, so that old prefixed names are replaced
by namespaces. Please consider the following class:

=== boundingbox.h ===
[...]
namespace VART {
class Transform; // forward declaration of class Transform
class BoundingBox {
friend std::eek:stream& operator<<(std::eek:stream& output, const
BoundingBox& box);
public:
[...]
void Transform(const Transform& trans);

It is generally a BAD IDEA(tm) to name your functions and your types
the same.
[...]
===============
1) I tried "class VART::Transform;" before "namespace VART {" which
gave me compile errors. Is the current declaration ok? Is there a
better way?

If you have to forward-declare a class in a namespace, you open the
namespace, declare the class, close the namespace. It should be fine.
2) The output operator is inside namespace VART. Could it be outside?
Users of this framework would fell more confortable if it was...

You could prefix it with '::' (meaning in the global namespace).
3) I get "boundingbox.h:36: error: declaration of 'void
VART::BoundingBox::Transform(const VART::Transform&)'
transform.h:24: error: changes meaning of 'Transform' from 'class
VART::Transform'" when compiling on g++. I don't see why
VART::BoundingBox::Transform conflicts with VART::Transform. What
could be done here?

You could (a) rename your function or (b) elaborate the name of the
type:

void Transform(const class Transform&);

But I'd try doing (a) first.

V
 
B

Bruno de Oliveira Schneider

Victor said:
It is generally a BAD IDEA(tm) to name your functions and your types
the same.

Could you elaborate on that? I really don't see why
VART::BoundingBox::Transform conflicts with VART::Transform.
If you have to forward-declare a class in a namespace, you open the
namespace, declare the class, close the namespace. It should be fine.

Then I guess the way I did (open the namespace once, forward-declare
Transform and declare BoundingBox) is better than opening the namespace
twice (once for forward declarations and then for the class
declaration), right?
> You could prefix it with '::' (meaning in the global namespace).

How do I do that? I tried:
=== begin code ===
namespace VART
{
class Transform;
class BoundingBox {
friend std::eek:stream& ::eek:perator<<(std::eek:stream& output, const
BoundingBox& box);
public:
[...]
=== end code ===
But g++ gives me:
error: 'std::eek:stream& operator<<(std::eek:stream&, const
VART::BoundingBox&)' should have been declared inside '::'
 
V

Victor Bazarov

Bruno said:
Could you elaborate on that? I really don't see why
VART::BoundingBox::Transform conflicts with VART::Transform.

If you try referring to 'Transform' inside 'VART::BoundingBox' class,
which 'Transform' would that be? Is that obvious? I am not saying
that you *can't* do that. I am saying that you *shouldn't*.
If you have to forward-declare a class in a namespace, you open the
namespace, declare the class, close the namespace. It should be
fine.

Then I guess the way I did (open the namespace once, forward-declare
Transform and declare BoundingBox) is better than opening the
namespace twice (once for forward declarations and then for the class
declaration), right?
Right.
You could prefix it with '::' (meaning in the global namespace).

How do I do that? I tried:
=== begin code ===
namespace VART
{
class Transform;
class BoundingBox {
friend std::eek:stream& ::eek:perator<<(std::eek:stream& output, const
BoundingBox& box);
public:
[...]
=== end code ===
But g++ gives me:
error: 'std::eek:stream& operator<<(std::eek:stream&, const
VART::BoundingBox&)' should have been declared inside '::'

So, the compiler tells you that you're referring to a function that has
not been declared. So declare it.

V
 
B

Bruno de Oliveira Schneider

Victor said:
If you try referring to 'Transform' inside 'VART::BoundingBox' class,
which 'Transform' would that be? Is that obvious? I am not saying
that you *can't* do that. I am saying that you *shouldn't*.

It seems pretty obvious to me :) Since method names are pointers to
code, they couldn't be where a class/type is expected. However, if you
say its not obvious to the compiler, I'll take it. The method has been
renamed. :)
You could prefix it with '::' (meaning in the global namespace).

How do I do that? I tried:
=== begin code ===
namespace VART
{
class Transform;
class BoundingBox {
friend std::eek:stream& ::eek:perator<<(std::eek:stream& output, const
BoundingBox& box);
public:
[...]
=== end code ===
But g++ gives me:
error: 'std::eek:stream& operator<<(std::eek:stream&, const
VART::BoundingBox&)' should have been declared inside '::'

So, the compiler tells you that you're referring to a function that has
not been declared. So declare it.

I don't get it. The declaration is the problem. I'll be referring to it
in the implementation. If that is not a declaration, then what is it?
 
V

Victor Bazarov

Bruno said:
It seems pretty obvious to me :) Since method names are pointers to
code,

The names are names. Take a look

struct Blah { operator int() { return 42;} };
int Blah() { return 73; }

If it were allowed (or accepted), what would this be

int i = Blah();

? Is that a call to the function Blah or is that an instantiation of
a temporary of type Blah and conversion to int? What value should 'i'
get?

Names become "pointers to code" only if they are used in particular way.
If the compiler cannot distinguish between them, it will complain. Even
if the compiler *can* tell one from the other, are you sure that *you*
know which one it picks? Are you sure everybody else can tell?
they couldn't be where a class/type is expected. However, if you
say its not obvious to the compiler, I'll take it. The method has been
renamed. :)

The point here is not that the compiler can't tell, it's that *you* or
anybody else reading the code can't.
You could prefix it with '::' (meaning in the global namespace).

How do I do that? I tried:
=== begin code ===
namespace VART
{
class Transform;
class BoundingBox {
friend std::eek:stream& ::eek:perator<<(std::eek:stream& output, const
BoundingBox& box);
public:
[...]
=== end code ===
But g++ gives me:
error: 'std::eek:stream& operator<<(std::eek:stream&, const
VART::BoundingBox&)' should have been declared inside '::'

So, the compiler tells you that you're referring to a function that
has not been declared. So declare it.

I don't get it. The declaration is the problem. I'll be referring to
it in the implementation. If that is not a declaration, then what is
it?

It's a "friend declaration". If you're referring to a qualified name in
a friend declaration, it must be declared prior to that. Add a "normal"
declaration of that function to the global namespace.

V
 
B

Bruno de Oliveira Schneider

Victor said:
It's a "friend declaration". If you're referring to a qualified name in
a friend declaration, it must be declared prior to that. Add a "normal"
declaration of that function to the global namespace.

So, you are saying I need to use this huge thing below:

===boundingbox.h===
namespace VART {
class BoundingBox;
}
std::eek:stream& operator<<(std::eek:stream& output, const VART::BoundingBox&
box);

namespace VART {
class BoundingBox {
friend std::eek:stream& ::eek:perator<<(std::eek:stream& output, const
BoundingBox& box);
[...]
===============

Is this the right thing to do?
 
V

Victor Bazarov

Bruno said:
Victor said:
It's a "friend declaration". If you're referring to a qualified
name in a friend declaration, it must be declared prior to that.
Add a "normal" declaration of that function to the global namespace.

So, you are saying I need to use this huge thing below:

===boundingbox.h===
namespace VART {
class BoundingBox;
}
std::eek:stream& operator<<(std::eek:stream& output, const
VART::BoundingBox& box);

namespace VART {
class BoundingBox {
friend std::eek:stream& ::eek:perator<<(std::eek:stream& output, const
BoundingBox& box);
[...]
===============

Is this the right thing to do?

AFAIK, unless you want to define this operator right there, inside the
class definition (which you could), then yes, it's the only thing to do.

V
 
B

Bruno de Oliveira Schneider

Victor said:
AFAIK, unless you want to define this operator right there, inside the
class definition (which you could), then yes, it's the only thing to do.

And if I want the operator to be friend of class BoundingBox, where
else could I define it?
 
V

Victor Bazarov

Bruno said:
And if I want the operator to be friend of class BoundingBox, where
else could I define it?

You can define it anywhere you want. The rule is simple: if you don't
have it declared (or defined, since a definition is a declaration)
before the compiler sees your 'friend' declaration, the compiler
*assumes* the function is at the *same namespace level* as the class.
If that's not true, then the function has to be declared before you can
declare it a friend. IOW, you can define it anywhere you want, but you
must declare it before the compiler encounters the friend declaration.
And if you always follow that rule (instead of relying on the compiler
guessing correctly where your function will be), you will never have
any problem. Be explicit, it will make your life simpler.

V
 
B

Bruno de Oliveira Schneider

Victor said:
You can define it anywhere you want. The rule is simple: if you don't
have it declared (or defined, since a definition is a declaration)
before the compiler sees your 'friend' declaration, the compiler
*assumes* the function is at the *same namespace level* as the class.
If that's not true, then the function has to be declared before you can
declare it a friend. IOW, you can define it anywhere you want, but you
must declare it before the compiler encounters the friend declaration.
And if you always follow that rule (instead of relying on the compiler
guessing correctly where your function will be), you will never have
any problem. Be explicit, it will make your life simpler.

So, I may declare it anywhere I want. But since the operator is a
friend of class BoundingBox and the friend declaration has to be inside
the class declaration, and the operator is not in same namespace as the
class, then it must be declared before the class declaration. Since I
must declare the operator before the class declaration, then I must
forward-declare the class, opening its namespace again.

So, it may be anywhere, but it has to be there. Am I missing something?
:)

Sorry about the irony. I really appreciate your help, but it seems to
me you are trying to make to broad explanations and missing the
point... that is a bit confusing...
 
V

Victor Bazarov

Bruno said:
Victor said:
[...explanation...]

So, I may declare it anywhere I want. But since the operator is a
friend of class BoundingBox and the friend declaration has to be
inside the class declaration, and the operator is not in same
namespace as the class, then it must be declared before the class
declaration. Since I must declare the operator before the class
declaration, then I must forward-declare the class, opening its
namespace again.

Yes, sounds right.
So, it may be anywhere, but it has to be there. Am I missing
something? :)

I guess you are. I am not going to find it for you, though. You have
to do it yourself. What is the "it" you're referring to? The operator
can be declared anywhere. To be declared a friend, the operator has
to be declared. Where? Anywhere you want. Just declare it. Now, if,
to declare the operator, you need to declare the class first, then declare
the damn class. Where? *Before the operator*.
Sorry about the irony.

It's not irony. It's an attempt at sarcasm.
I really appreciate your help, but it seems to
me you are trying to make to broad explanations and missing the
point... that is a bit confusing...

*I* am missing the point? Which point am I missing? That you don't
want to do what is required by the language? No, I'm definitely not
missing *that* point.

V
 

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,792
Messages
2,569,639
Members
45,353
Latest member
RogerDoger

Latest Threads

Top