can anybody please explain the following warning to me
../include/zthread/PoolExecutor.h:58: warning:
'ZThread::PoolExecutor' has a field 'ZThread::PoolExecutor::_impl' whose
type uses the anonymous namespace
Many thanks for a hint,
Helmut Jarausch
Lehrstuhl fuer Numerische Mathematik
RWTH - Aachen University
D 52056 Aachen, Germany
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
> can anybody please explain the following warning to me
>
> ../include/zthread/PoolExecutor.h:58: warning:
> 'ZThread::PoolExecutor' has a field 'ZThread::PoolExecutor::_impl' whose
> type uses the anonymous namespace
>
1. A namespace with no identifier before an opening brace produces an
unnamed namespace. Each translation unit may contain its own unique
unnamed namespace.
2. Items defined in an unnamed namespace have internal linkage.
What you have got is a *warning*, and the above two points may help
explaining why the compiler issued such a warning.
regards,
Jyoti
>
> 2. Items defined in an unnamed namespace have internal linkage.
>
Is that true? Where is it guaranteed by the standard? This has
not been my experience.
MV
--
I do not want replies; please follow-up to the group.
Each .cpp file you compile into your project ("translation unit") has
its own unique anonymous namespace. It's a misnomer to say "the"
anonymous namespace because that implies there is only one.
Thus, declaring types in an anonymous namespace in a header has the
subtle effect of putting that type in a different namespace for every
translation unit that includes your header.
Perhaps it's easier to describe the problem with an example:
// common.hpp
#ifndef COMMON_HPP
#define COMMON_HPP
namespace {
class Impl { };
} // anonymous
class X {
Impl data;
};
#endif // COMMON_HPP
// file1.cpp
#include "common.hpp"
void f() {
X object;
}
// file2.cpp
#include "common.hpp"
void g() {
X object;
}
When we compile file1, common.hpp declares (anon)::Impl in file1's
anonymous namespace, and so class X is something like this under the
hood:
namespace file1_anon_ns {
class Impl { };
}
// inside file1
class X {
file1_anon_ns::Impl data;
};
But when we're compiling file2, we also include common, which puts
(anon)::Impl in file2's anonymous namespace, something like this:
namespace file2_anon_ns {
class Impl { };
}
// inside file2
class X {
file2_anon_ns::Impl data;
};
Now the problem should be clear: the definition of X is not the same
in different translation units, violating the One Definition Rule.
--
Chris
Right.
> 2. Items defined in an unnamed namespace have internal linkage.
Wrong, they have normal external linkage until they are declared
otherwise (i.e. with the static qualifier). But this has a similar
effect like internal linkage. Unnamed namespace entities are
not available in different TU (translation units), because they
cannot be named outside, due to their unique, but *unknown*
name (for the programmer). Therefore explicit static linkage
specification via the static keyword is deprecated as of
[namespace.unnamed]/2:
"The use of the static keyword is deprecated when declaring
objects in a namespace scope (see annex D); the unnamed-
namespace provides a superior alternative."
In other words: Regarding linkage rules an unnamed namespace
does not behave differently as named namespace.
*Usually* an unnamed namespace in a (shared) header file
should be avoided, because the seemingly same entity declared
there will be actually different enties for each TU which includes
this header. But in this regard this is quite similar to an entity
declared with internal linkage in a shared header.
Greetings from Bremen,
Daniel Krügler
The problem here though is that it will be unusuable in other translation
units, as only a forward declaration could be made for
ZThread::PoolExecutor.
If one were to include a full class definition in a different translation
unit, the two definitions would not be equivelent since the _impl member
would have a different type in each. This results in undefined behavior
as per [basic.def.odr]/5.
--
IIRC it is false. Names declared in an unnamed namespace have external
linkage but their fully qualified name is unutterable.
--