Boost logo

Boost :

From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2002-01-30 14:19:14


----- Original Message -----
From: Yitzhak Sapir <ysapir_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Wednesday, January 30, 2002 11:39 AM
Subject: RE: [boost] boost bind/functional/reference wrapper/mem_fn

> [...]
> namespace
> {
> inline boost::_bi::arg<1> _1() { return boost::_bi::arg<1>(); };
> inline boost::_bi::arg<2> _2() { return boost::_bi::arg<2>(); };
> inline boost::_bi::arg<3> _3() { return boost::_bi::arg<3>(); };
> inline boost::_bi::arg<4> _4() { return boost::_bi::arg<4>(); };
> inline boost::_bi::arg<5> _5() { return boost::_bi::arg<5>(); };
> inline boost::_bi::arg<6> _6() { return boost::_bi::arg<6>(); };
> inline boost::_bi::arg<7> _7() { return boost::_bi::arg<7>(); };
> inline boost::_bi::arg<8> _8() { return boost::_bi::arg<8>(); };
> inline boost::_bi::arg<9> _9() { return boost::_bi::arg<9>(); };
> }
>
> This way it can remain one header with no extra defines based on whether
> you want/don't want precompiled headers. Or is something wrong with
> this code?
>
Jus a note: The definitions of the inline functions _X() are inside an
unnamed namespace.

Unless I'm missing something, it is required that inline functions be
declared inside an unnamed namespace.
Just for the records, I'll explain this issue in some detail:

Using C terminology, a header might need to declare objects at "file scope",
traditionally called static objects.
'static' objects have "internal linkage", meaning that their names can be
seen from other scopes, but each translation unit (TU) will have its own
distinct definition of these objects.

A library could require visible objects (i.e., bind requires _X). If those
objects are declared without external linkage, the linker will encounter
duplicate symbols because different TUs will have the same definition.
Usually, if the objects are not meant to be 'shared' across different TUs,
libraries declare those objects with internal linkage. Each TU that includes
their declarations receives a distinct copy (with a distinct symbol), thus
there are no duplicate symbols seen by the linker.

In C, this is accomplished using the 'static' specifier.

In C++, an object [first] declared with 'static' or 'const' has internal
linkage.
(* in C, however, 'const' doesn't specify any linkage).

However, in C++, the usage of 'static' for file scope declarations is
deprecated in favor of a technique which has a similar effect.

Both in C and C++, objects with "external linkage" share the same
definition (and symbol) across translation units. Therefore, these objects
are required to have the same address in all TUs, so the linker can collapse
all initially separated definitions into a single one.

A variable declared with namespace scope, such as:

namespace boost {

    boost::_bi::arg<1> _1;
}

has external linkage by default. It means that '_1' will be the same object
in every TU.

An "unnamed namespace" introduces a nested namespace with a hidden name,
along with an implicit using directive that allows this hidden name to be
implicit in the object id.

Therefore, if '_1' appears inside an unnamed namespace:

namespace boost {
namespace {
    boost::_bi::arg<1> _1;
}
}

its fully qualified-id (name) is actually something like:

boost::unique_to_the_current_TU::_1.

But since the hidden namespace "unique_to_the_current_TU" is brought to
namespace 'boost' with an implicit using directive, you don't have to type
it and can refer to it simply as "boost::_1"

However, the object has whatever linkage it is given, and in this case it is
external linkage since it isn't static nor const.

Having external linkage means that boost::_1 is totally visible from every
TU, but, since its name incorporates the hidden namespace which is specific
to each TU, there are no duplicate symbols seen by the linker.

IOW, we put object declarations/definitions inside an unnamed namespace in
order to avoid duplicate symbols across TUs, emulating the effect of
internal linkage, and when we can't give the objects external linkage
because that would require an additional source file to be supplied.

non-inline functions have external linkage by default, thus they require a
single definition in a single source file. Conversely, inline functions have
internal linkage by default, so they don't require a separate source file.

As a conclusion, we don't need to put inline functions in an unnamed
namespace because they have internal linkage
(unless of course there is something I misunderstand or not seeing...)

Fernando Cacciola
Sierra s.r.l.
fcacciola_at_[hidden]
www.gosierra.com


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk