|
Boost : |
From: David Abrahams (dave_at_[hidden])
Date: 2004-05-07 19:55:20
Ian McCulloch <ianmcc_at_[hidden]> writes:
> David Abrahams wrote:
>
>> "Arkadiy Vertleyb" <vertleyb_at_[hidden]> writes:
>>
>>> "David Abrahams" <dave_at_[hidden]> wrote
>>>
>>>> Any time a template is instantitated, all names in its definition
>>>> must map to the same entities in each translation unit, or you
>>>> violate the ODR. By definition, names in the unnamed namespace
>>>> refer to distinct entities in each translation unit.
>
> But typedef only introduces aliases for an existing type. Does that
> qualify for "map[s] onto the same entity" ?
Your question isn't specific enough for me to answer.
>>> IOW, such templates in different translation units will be
>>> absolutely the same, although in each translation unit the
>>> compiler will have to instantiate different intermediate classes
>>> in order to produce them.
>
> Those intermediate classes are in an unnamed namespace and not an ODR
> violation in themselves?
>
Not in and of themselves. Their use in the same template in multiple
translation units is a violation, IIUC.
> If I understand correctly, you are saying that
>
> // header.h
> namespace {
> typedef int foo;
> }
>
> struct bar { foo f; };
>
> // end header.h
>
> causes an ODR violation if type bar (or even foo) is used in more
> than one translation unit?
That appears to be clearly spelled out below. AFAICT unnamed namespaces in
header files are evil.
> Can you quote chapter and verse? (or perhaps that should be asked
> on c.s.c++).
Probably ;-) It's all there right under "One definition rule" in the
standard.
3 Basic concepts 3.2 One definition rule
-5- There can be more than one definition of a class type (clause
class), enumeration type (dcl.enum), inline function with external
linkage (dcl.fct.spec), class template (clause temp), non-static
function template (temp.fct), static data member of a class template
(temp.static), member function [core 249: template of a class
template ] (temp.mem.func), or template specialization for which some
template parameters are not specified (temp.spec, temp.class.spec) in
a program provided that each definition appears in a different
translation unit, and provided the definitions satisfy the following
requirements. Given such an entity named D defined in more than one
translation unit, then
- each definition of D shall consist of the same sequence of
tokens; and
- in each definition of D, corresponding names, looked up according
to basic.lookup, shall refer to an entity defined within the
definition of D, or shall refer to the same entity, after
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
overload resolution (over.match) and after matching of partial
template specialization (temp.over), except that a name can refer
to a const object with internal or no linkage if the object has
the same integral or enumeration type in all definitions of D,
and the object is initialized with a constant expression
(expr.const), and the value (but not the address) of the object
is used, and the object has the same value in all definitions of
D; and
- in each definition of D, the overloaded operators referred to,
the implicit calls to conversion functions, constructors,
operator new functions and operator delete functions, shall refer
to the same function, or to a function defined within the
definition of D; and
- in each definition of D, a default argument used by an (implicit
or explicit) function call is treated as if its token sequence
were present in the definition of D; that is, the default
argument is subject to the three requirements described above
(and, if the default argument has sub-expressions with default
arguments, this requirement applies recursively).*
[Footnote: dcl.fct.default describes how default argument names are
looked up. --- end foonote]
- if D is a class with an implicitly-declared constructor
(class.ctor), it is as if the constructor was implicitly defined
in every translation unit where it is used, and the implicit
definition in every translation unit shall call the same
constructor for a base class or a class member of D.
[Example:
// translation unit 1:
struct X {
X(int);
X(int, int);
};
X::X(int = 0) { }
class D: public X { };
D d2; // X(int) called by D()
// translation unit 2:
struct X {
X(int);
X(int, int);
};
X::X(int = 0, int = 0) { }
class D: public X { }; // X(int, int) called by D();
// D()'s implicit definition
// violates the ODR
--- end example]
- If D is a template, and is defined in more than one translation
unit, then the last four requirements from the list above shall
apply to names from the template's enclosing scope used in the
template definition (temp.nondep), and also to dependent names at
the point of instantiation (temp.dep). If the definitions of D
satisfy all these requirements, then the program shall behave as
if there were a single definition of D. If the definitions of D
do not satisfy these requirements, then the behavior is
undefined.
14.6.4.1 Point of instantiation 14 Templates
7 A specialization for a function template, a member function
template, or of a member function or static data member of a class
template may have multiple points of instantiations within a
translation unit. A special- ization for a class template has at most
one point of instantiation within a translation unit. A specialization
for any template may have points of instantiation in multiple
translation units. If two different points of instantiation give a
template specialization different meanings according to the one
definition rule (3.2), the program is ill-formed, no diagnostic
required.
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk