Re: question on c++ constants?
On Oct 16, 6:58 pm, gpderetta <gpdere...@gmail.com> wrote:
On Oct 16, 5:46 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
Gennaro Prota wrote:
gpderetta wrote:
On Oct 16, 12:12 pm, James Kanze <james.ka...@gmail.com> wrote:
[...]
Refer to almost anything in an anonymous namespace
in a header, and you end up with undefined behavior.
Is this exception explicitly given in the standard or
must be inferred somehow? Do you have a pointer?
An unnamed namespace goes --as per language definition--
like this
namespace unique { }
using namespace unique ;
namespace unique { /* your stuff */ }
where "unique" is a name generated by the compiler, unique
per *translation unit* (not file). So, if you include e.g.
// a.hpp
namespace {
class A {} ;
}
from e.g. f1.cpp and f2.cpp you end up with two A classes, one
in namespace --let's call it-- f1_unique, and another one in
f2_unique. Now, consider two source files which include the
following:
// useful.hpp
#include "a.hpp"
class useful
{
A a_ ;
...
} ;
Those two source files will contain two different
definitions of class useful.
This is a great example that could lead to quite an obscure coding
guideline. Of course, a good compiler would issue a warning if a type
from an unnamed namespace would be used to define another type which
isn't in the [same] unnamed namespace. We could lobby the compiler
vendors to include such analysis, it wouldn't be difficult for them to
introduce, I suppose.
It is not just a matter of types, consider this:
// in foo.hpp
struct my_functor_type {...};
namespace { my_functor_type bar; }
template<class T> void foo(T x) {
bar(x);
}
Now, if foo is instantiated in two translation units with the
same T, it will lead to ODR violation.
Yes. This is what I consider the real problem. Templates
require their definition to be in the header file, and the
one definition rule to apply to all potential instantiations
(even if in practice, most compilers will just pick one, and
throw out any others).
This is not a made up example, I often find the need to name
function object instances in header files, but, if the
anonymous namespace is dropped, you will get multiple
definitions for 'bar'. The only workaround I know (from the
boost mailing list) is:
template <class F> struct instance_of { static T value; };
template<class T> T instance_of<T>::value = {}
namespace { my_functor_type const& bar =
instance_of<my_functor_type>::value; }
template<class T> void foo(T x) {
bar(x);
}
Typical Boost:-). Why do simple when you can do complicated:
namespace Whatever_Private
{
extern my_functor_type bar ;
} ;
Or if you really need to be headers only:
namespace Whatever_Private
{
inline my_functor_type& bar()
{
static my_functor_type theOneAndOnly ;
return theOneAndOnly ;
}
} ;
In sum, the classical solutions (but it just ain't Boost if it
ain't got the templates).
(Seriously, there's a lot I like about Boost. But they do get
carried away sometimes.)
Now there won't be any ODR violations in 'foo', if the ODR
rule is interpret as only requiring all symbols to bind to the
same objects in all translation units.
If you want the library to be headers only, then you need to
encapsulate the definition in something which can appear in
multiple compilation units: a template or an inline function.
Generally, you're better off dropping the headers only
requirement, however.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34