---------------- library.h ---------------------------
namespace foo_2_5
{
}
//an alias to the latest version of foo
namespace foo = foo_2_5;
------------------------------------------------------
---------------- application.h -----------------------
#include "library.h"
namespace foo // <== problem
{
//attempt to forward declare a class
//from "latest" foo namespace
class someclass;
};
------------------------------------------------------
MSVC 7.0 is happy with this code. Sun Forte 5.1 and
Comeau online are not. I suspect they are correct but if it
is so, how to forward declare the someclass without
knowing/caring about foo_2_5 namespace?
Eugene
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
The last two are, IIRC, correct. You cannot use a namespace alias for
adding material to a namespace. I think this is an issue that we need to
address a future standard because it means we cannot use namespace
aliases to mask library versions (in versioned namespaces) if the user
needs to add to the namespace.
--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow ACCU
> In message <A62cndoMHuZ...@speakeasy.net>, Eugene Gershnik
> <gers...@nospam.hotmail.com> writes
>>MSVC 7.0 is happy with this code. Sun Forte 5.1 and
>>Comeau online are not. I suspect they are correct but if it
>>is so, how to forward declare the someclass without
>>knowing/caring about foo_2_5 namespace?
>
> The last two are, IIRC, correct. You cannot use a namespace alias for
> adding material to a namespace. I think this is an issue that we need to
> address a future standard because it means we cannot use namespace
> aliases to mask library versions (in versioned namespaces) if the user
> needs to add to the namespace.
I am usure, but How about
---------------- library.h ---------------------------
namespace foo_2_4
{
// all the stuff under version 2.4
}
namespace foo_2_5
{
// all the stuff under version 2.5
}
#ifndef VERSION
VERSION = 2_5
#endif
namespace foo
{
#if VERSION == 2_5
using namespace foo_2_5;
#else if VERSION == 2_4
using namespace foo_2_4;
#else
#error "You Idiot"
#endif
}
---------------- application.h -----------------------
#include "library.h"
// uncomment if You want to use the stone age lib
// #define VERSION 2_4
namespace foo
{
// do whatever You want
};
I found at least Intel's C++ propagates all
names as I (the maybe wrongheaded one) expect them.
I also use this technique to get rid of trilliards of
using declaratives and to only import those names I want to
be visible:
namespace Convenience
{
using std::list;
using boost::mpl::if_;
using garbage::from::my::own::lib;
using comp::lang::cpp::moderated;
using namespace withoutsurprises;
}
int main()
{
using namespace Convenience; // an alias for the using stuff above?
}
Any caveats I missed?
Markus
Still doesn't solve forward declaration problem.
namespace foo
{
class someclass;
};
will forward declare foo::someclass and not
foo_2_5::someclass.
Unfortunately it looks like the only way to use forward
declares with versioned namespaces is to rely on
preprocessor rather than namespace aliases. I only
hope that MSVC will not fix its "bug" in the next release
and Sun Forte and others will deliberately introduce it :-)
Eugene
I will leave it to the experts to explain but what you did was not the
same as a namespace alias and there are some nasty surprises waiting if
you try to do it that way. Using directives introduce new wrinkles in
name look-up. For plain application level code they usually work fine
but by the time you throw templates into the mix you will find that
things do not always work.
--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow ACCU
And that C++0x finds a way to fix namespace aliases.
--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow ACCU
It would also be very handy to be able to say
namespace x::y {
> In message <b4nhq1$210827$1...@ID-153032.news.dfncis.de>, Markus Werle
> <numerical....@web.de> writes
>>Any caveats I missed?
>
>
> I will leave it to the experts
Your turn then.
> to explain but what you did was not the
> same as a namespace alias and there are some nasty surprises waiting if
> you try to do it that way. Using directives introduce new wrinkles in
> name look-up.
Ah! Again ADL sucks?
> For plain application level code they usually work fine
> but by the time you throw templates into the mix you will find that
> things do not always work.
Examples, please - or at least a link to a recent discussion about this.
best regards,
Markus
C++ is not known for consistency, but it is consistent in that all names
must
be declared inside the scope in which it will live. The only place where you
can avoid the nested braces and instead use typedefs or namespace aliases
are in nested class definitions such as
namespace N
{
class C0
{
class C1;
};
}
typedef N::C0 T;
namespace A = N;
class A::T::C1
{
class C2 {};
};
Here the compiler has to resolve the path elements A and T before it
can correctly declare C2. However, both of these were declared with a
different syntax so the qualified name A::T::C1 is unambigous.
But if syntax like
namespace A
{
}
were allowed, the compiler would interpret it either as an extension of N
or as a new namespace A, depending on whether it had already seen the
namespace alias definition of A. That's a source of unexpected errors.
Technically the problem arises since a namespace extension has identical
syntax to an original namespace definition.
Tom Houlder
thou...@houlder.net
Chic - C++ without hassles
http://www.houlder.net
Lookup in a using directive comes with two gotchas. Firstly, a directive
is only used for lookup if the compiler doesn't find anything else in the
normal lookup in that scope. This gives the following surprising legal
code:
namespace N0
{
class C {};
}
namespace N1
{
// Two identical names in the same scope!
using namespace N0;
C c0; // N0::C
class C {};
C c1; // N1::C
}
The other quirk is that names introduced through using directives are
not treated as names found in the scope were the using directive is
located, but rather in some scope above. The following code is good:
namespace N0
{
class C {};
}
namespace N1
{
using namespace N0;
C c0; // N0::C
}
but if you now introduce another C in the global namespace:
class C {};
namespace N1
{
C c1; // Ambigous!
}
The reason is that the compiler treats first C found through the using
directive as it was a name in the innermost scope common to the
location of the using directive and the entity it found. The
innermost common scope of ::N0 and ::N1 is ::, i.e. the global scope.
But now there is another C in the global scope so the lookup is
ambiguous.
This last issue has theoretically far-reaching implications concerning
encapsulation: you cannot modify a namespace without taking
into account the existing name bindings *between* all nested
namespaces below it.
Tom Houlder
thou...@houlder.net
Chic - C++ without hassles
http://www.houlder.net
[snip]
> But if syntax like
>
> namespace A
> {
> }
>
> were allowed, the compiler would interpret it either as an extension of N
> or as a new namespace A, depending on whether it had already seen the
> namespace alias definition of A. That's a source of unexpected errors.
>
But the same problem would arise if one would use preprocessor for
namespace versioning. In both cases you usually will get meaningfull error
messages from the linker so there is a little chance that the problem will
go
unnoticed. (It is surely possible to construct an example where linker
will not notice the problem but I doubt it will be relevant to real-life
code)
There is nothing new here. Exactly the same kind of problems could
happen every time one uses typedef. I think C++ gives one plenty of
opportunities to give different meanings to the same name :-)
> Technically the problem arises since a namespace extension has identical
> syntax to an original namespace definition.
>
Good point. How about this syntax
in namespace foo
{
class someclass;
}
where "in namespace" is supposed to mean "I am going to extend foo
namespace which must have been declared prior to this point"?
Eugene
I agree it's not a showstopper, but you will always need to use the
preprocessor to include the original namespace definition and the
alias if you want to avoid changing client code when you change
the alias. But, unless there are other issues, I agree with you that
allowing namespace aliases for naming scopes could be beneficial.
> There is nothing new here. Exactly the same kind of problems could
> happen every time one uses typedef. I think C++ gives one plenty of
> opportunities to give different meanings to the same name :-)
You're not allowed to use a typedef for a class definition:
class C;
typedef C T;
class T // Illegal.
{
};
> > Technically the problem arises since a namespace extension has
identical
> > syntax to an original namespace definition.
> >
>
> Good point. How about this syntax
>
> in namespace foo
> {
> class someclass;
> }
>
> where "in namespace" is supposed to mean "I am going to extend foo
> namespace which must have been declared prior to this point"?
New keywords are always frowned at, so let's instead use the pure
virtual hack for an original namespace definition...
namespace foo = 0
{
}
Seriously, even though this will catch the error at compile time,
it's not worth it.
Tom Houlder
thou...@houlder.net
Chic - C++ without hassles
http://www.houlder.net
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
Sure. I've meant something entirely different like
the following (simplified but taken from real code):
in header 1:
typedef Library1::Logger Logger
typedef unsigned int uint32_t;
in header 2:
typedef Library2::Logger Logger
typedef unsigned long uint32_t;
in header 3:
void bar(const Logger & logger);
void foo(uint32_t value);
which obviously declares different things
depending on what was included before.
This problem was present in C and C++
for ages and no one was seriously hurt
so I do not see any reason why namespace
aliases should behave any different from type
aliases.
Eugene