Topic: Linkage of namespace scope reference


Author: johnchx2@yahoo.com
Date: Wed, 14 Jun 2006 18:46:18 CST
Raw View
"Alf P. Steinbach" wrote:
> * johnchx2@yahoo.com:
> > Alf P. Steinbach wrote:
> >
> >> Formally that's backwards, because for a reference it's the initializer
> >> that determines whether the declaration is a definition, not the other
> >> way around.
> >
> > It has nothing to do with whether the name being declared is a
> > reference, it has to do with whether the name being declared is
> > explicitly declared extern.
> >
> > Any declaration with the extern keyword is also a definition if and
> > only if an explicit initializer is present.
>
> How is that different from what I wrote?

I disagree with the phrase "for a reference" in your formulation.  For
a declaration without an explicit initializer to be a non-definition,
it is neither necessary nor sufficient for the name to be declared with
reference type.  What is necessary (and sufficient) is for "extern" to
appear in the declaration.  The rules for reference and non-reference
declarations seem consistent in this regard.

Perhaps I misunderstood you, but I thought you were suggesting that
references were a special case.


> >  Declarations without the
> > extern keyword are always definitions.  (I'm assuming we're just
> > talking about variable declarations; static data members, functions and
> > types follow...sigh...different rules.)
>
> Well, a reference isn't a variable, so that's not what we're talking about.

True; I was groping around for a shorthand expression and came up with
a bad one.

It would be better to say: a declaration is a definition unless 3.1/2
says it's not.  One of the things 3.1/2 says isn't a definition is a
declaration that includes the extern specifier and doesn't include an
initializer.


> >> The 'const' for something that a reference refers to is not a 'const'
> >> for the reference itself.
> >>
> >> The analogous case for non-reference would be a const pointer's linkage
> >> being determined by the constness of what the pointer points to.
> >
> > I think that is a mis-perception
>
> What is a mis-perception, do you think?

Perhaps "mis-perception" isn't the best phrase.  Say rather, it's a
poor analogy.


> > that comes from thinking of references
> > as automatically dereferenced pointers, rather than as what the
> > standard says they are: pure aliases.  Consider:
> >
> >    const int a = 0;
> >    const int& b = a;
> >
> > "a" names a const object.  "b" also names a const object (as it
> > happens, the same one).  They're alike.  It's non-sensical to think of
> > "b" as naming "the reference", because no such object exists to name.
>
> In order to declare 'b' as an 'extern' reference you need to be aware
> that it's a reference, and declare it in other translation units as a
> reference.

Sure, but that's beside the point that I'm trying to make.   Let me try
to make it better.  Once you accept that const-ness can affect the
default linkage of a name (and *that's* the part that *I* find
surprising and arbitrary), it shouldn't be surprising that it's the
const-ness of the lvalue expression formed by the use of the name that
matters.

So:

  const int a = 0;
  const int* pa = &a;  // lvalue "a" has const type
  const int& b = a;
  const int* pb = & b; // lvalue "b" has const type
  const int** ppb = & pb;  // lvalue "pb" had non-const type

"a" and "b" have internal linkage because the corresponding lvalues
have const type.  "pa" and "pb" have external linkage because the
corresponding lvalues have non-const type.  The types of "*pa" and
"*pb" don't enter into it.

There's a verbal analogy created by the phrases "pointer-to-const" and
"reference-to-const."  But this is purely word-play, and it is
misleading.  A name declared with type const T* denotes an object of
non-const pointer type.  A name declared with type const T& denotes an
object of type const T.  It does not denote "a reference".

> I think the only sensible way to think of 'b' is as a reference.
>
> For the purpose of 'extern', which is what this tread is all about, it
> won't do to treat 'b' as simply an alternate name for an object.
>
> 'extern const int b;' in some other translation unit does not refer to
> 'extern const int& b = a' in this one.


The question isn't really whether we can ignore the fact that b has
reference type, but whether it is analagous to a pointer to the
referenced type.  I don't think that analogy is a good one, for the
very reason you give: it leads to the wrong conclusion about the
linkage of the name.  (It also gives a false impression of what the
name denotes.)


> > (Of course, in some situations, the implementation will use a pointer
> > "under the hood," e.g. for reference members.  But that's an
> > implementation detail, irrelevant to the *concept* of references.)
>
> Details matter, understanding the implementation matters, and yes,
> concepts matter: none of it is irrelevant.

Sure.  But what I'm driving at is that by chosing which aspects to
emphasize, it is possible to come up with exposition that is either
more or less confusing.  I don't think that there's any doubt that it
is possible to arrive at an exposition of these rules that is both
confusing and correct.  (Arguably, the standard itself if sufficient
evidence of that.)  The interesting question is whether there is also
an exposition which is both correct and "non-confusing."

I think that, at least for non-members, there is.  Something like:

(a) All declarations are definitions, except when explicitly declared
extern.  An extern declaration is a definition if and only if it
includes an explicit initializer.

(b) Some definitions require an explicit initializer, specifically:
definitions of variables of const type (for types without a
user-defined default constructor) and definitions of names with
reference type.

(c) Names declared with const type (that is, names whose evaluation as
an lvalue will have const type) have internal linkage by default.
Names declared with non-const type have external linkage by default.
Names can be given non-default linkage by means of keywords static and
extern or by means of a linkage specifier.

These may not cover every single case (I'm leaving members out, for
example), but nothing -- with the possible exception of (b), which I
suspect is inherited from C -- jumps out at me as wildly arbitrary.  Do
you disagree?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Alf P. Steinbach" <alfps@start.no>
Date: Mon, 12 Jun 2006 09:37:13 CST
Raw View
* kanze:
> "Alf P. Steinbach" wrote:
>>    * If a reference has external linkage because it's explicitly
>>      declared 'extern', the initializer can be omitted (   8.5.3/3, "The
>>      initializer can be omitted only ... where the extern specifier is
>>      explicitly used").
>
>>    * If, OTOH., a reference has external linkage because it doesn't
>>      refer to const and hasn't been declared 'static', the initializer
>>      cannot be omitted.
>
>> So the requirement to initialize locally hinges not on the
>> effective linkage of the reference, i.e. on whether the intent
>> is to initialize it once, in some translation unit, but on
>> precisely how it acquired external linkage, which, as I see
>> it, doesn't matter at all wrt. safety or correctness or any
>> sound criterion for a local initialization requirement, and is
>> inconsistent with the requirements for other types.
>
> Not really.  You're missing another important point: which
> declarations are in fact definitions.  A reference at namespace
> scope which is not declared extern (or a reference with an
> initialization, even if it is declared extern) is a definition.
> There can only be one definition of the reference in the entire
> program (or else you have undefined behavior -- and typically,
> an error from the linker), and that definition must have an
> initialization clause.

I don't think I missed that point.  That was my point.  It's a peculiar,
seemingly arbitrary special case for references.  The way a not
explicitly "extern" reference declaration is a definition is similar to
how a not explicitly "extern" constant declaration is a definition.  But
the way such a reference can have external linkage by default is
different from constants.

At namespace scope, we have

    T& r = o;         // External linkage, definition because of type.
    T* const p = &o;  // Internal linkage, definition because of type.

One would expect, and I did originally expect, that when initialization
is required, internal linkage is implied, but this special case breaks
that expectation  --  for no good reason that I can see.

Perhaps the best approach is to view constants as the special case.

Or, come to think of it, to view both references and constants as
special cases, which makes ordinary variables a third special case, so
that all we have is a collection of special cases...

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Mon, 12 Jun 2006 21:38:46 CST
Raw View
Alf P. Steinbach wrote:

> One would expect, and I did originally expect, that when initialization
> is required, internal linkage is implied, but this special case breaks
> that expectation  --  for no good reason that I can see.

I don't think I understand why "one would expect" any relationship
between the linkage of a name and whether an explicit initializer is
required where the name is defined.  Consider:

struct foo1 {  };
struct foo2 { foo2() {} };

namespace ns {

   int a;         // external linkage; legal
   static int b;  // internal linkage; legal

   const int c;   // internal linkage; illegal
   int& d;        // external linkage; illegal
   const int& e;  // internal linkage; illegal

   const foo1 f1; // internal linkage; illegal
   const foo2 f2; // internal linkage; legal

}

All of the above are definitions.

Neither a nor b requires an explicit initializer, even though a has
external linkage and b has internal linkage.  c and e have internal
linkage and require initializers, but d (with external linkage) also
requires an initializer.  Finally, both f1 and f2 have internal
linkage, but only f1 requires an initializer.

The extern keyword doesn't change whether a definition requires an
initializer; it only changes whether a declaration without an
initializer is also an (ill-formed) definition.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: alfps@start.no ("Alf P. Steinbach")
Date: Tue, 13 Jun 2006 15:25:21 GMT
Raw View
* johnchx2@yahoo.com:
> Alf P. Steinbach wrote:
>
>> One would expect, and I did originally expect, that when initialization
>> is required, internal linkage is implied, but this special case breaks
>> that expectation  --  for no good reason that I can see.
>
> I don't think I understand why "one would expect" any relationship
> between the linkage of a name and whether an explicit initializer is
> required where the name is defined.

It's an expectation that the language does not have (too many!)
completely arbitrary requirements.  For internal linkage there's no need
to just declare a reference or constant, and the possibility of just
declaring is a bit dangerous, hence the requirement of initialization
makes sense in that context.  But the point of external linkage is to
have one definition and many just declarations, so the requirement
doesn't make sense in that context: for external linkage it's arbitrary.

Another point of view is that it's the external linkage of "T& r=o;"
that's arbitrary.

Anyway, it's arbitrary, against expectation: I doubt that anybody
frequenting this group has ever written "T& r=o;" to define a reference
that's used in other translation units.


[snip]
> The extern keyword doesn't change whether a definition requires an
> initializer;

True, because a reference definition always requires an initializer.


> it only changes whether a declaration without an
> initializer is also an (ill-formed) definition.

Typo?  Sorry, I can't parse that.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Tue, 13 Jun 2006 11:51:06 CST
Raw View
"Alf P. Steinbach" wrote:
> * johnchx2@yahoo.com:
> > The extern keyword doesn't change whether a definition requires an
> > initializer;
>
> True, because a reference definition always requires an initializer.
>
>
> > it only changes whether a declaration without an
> > initializer is also an (ill-formed) definition.
>
> Typo?  Sorry, I can't parse that.
>

Yeah...it makes my eyes cross too.  But it says what I mean.  For
instance:

  T& t;

is a well-formed declaration AND an ill-formed definition.  But:

  extern T& t;

is a well-formed declaration that is NOT a definition.

So the presence or absence of extern only affects whether the
well-formed declaration is also an ill-formed definition.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Manfred von Willich" <manfred@techniroot.co.za>
Date: Tue, 13 Jun 2006 16:17:04 CST
Raw View
This thread is an illustration of the non-intuitive nature of the C++
syntax/semantics: various simple concepts have to be inferred by
complex rules; concepts such as constness, defined/declared, PODness,
static/dynamic initialization, linkage, whether initialised.  A keyword
for each would have been nice, but will remain a dream.

The complex way in which semantics tie in with syntax in C++ (e.g.
"const" affect linkage depending on context, but cannot be used with a
reference) leads to non-intuitiveness.  This does not mean that there
is lack of consistency in the underlying semantics, once you find a
construct that translates to the desired semantics.  A reference is in
essence an immutable (const) variable, and behaves accordingly.  It may
be optimized away, it may have TU-local or extern linkage etc.  That
"const" affects linkage is really unnecessary and unfortunate, but this
is how it has been defined.  Requiring initialization of immutable
variables is also strictly speaking unneeded.

My point is simply this:  Once one has converted the input program into
semantics via the lamentably complex rules, the behaviour is generally
intuitive and straightforward.  The problem is really one of how to
express the desired properties of an entity in C++, not of
counter-intuitive behaviour of those properties.

Perhaps an "official interpretation" of the standard (written around
orthogonal semantics, rather than rules of interpretation) would save a
lot of people confusion and time, including the committee members.  It
may also encourage a more orthogonal and hence simpler approach to
future changes.  How about it, committee?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Wed, 14 Jun 2006 09:35:18 CST
Raw View
Alf P. Steinbach wrote:
> * kanze:
> > "Alf P. Steinbach" wrote:
> >>    * If a reference has external linkage because it's
> >>      explicitly declared 'extern', the initializer can be
> >>      omitted (   8.5.3/3, "The initializer can be omitted
> >>      only ... where the extern specifier is explicitly
> >>      used").

> >>    * If, OTOH., a reference has external linkage because it
> >>      doesn't refer to const and hasn't been declared
> >>      'static', the initializer cannot be omitted.

> >> So the requirement to initialize locally hinges not on the
> >> effective linkage of the reference, i.e. on whether the
> >> intent is to initialize it once, in some translation unit,
> >> but on precisely how it acquired external linkage, which,
> >> as I see it, doesn't matter at all wrt. safety or
> >> correctness or any sound criterion for a local
> >> initialization requirement, and is inconsistent with the
> >> requirements for other types.

> > Not really.  You're missing another important point: which
> > declarations are in fact definitions.  A reference at
> > namespace scope which is not declared extern (or a reference
> > with an initialization, even if it is declared extern) is a
> > definition.  There can only be one definition of the
> > reference in the entire program (or else you have undefined
> > behavior -- and typically, an error from the linker), and
> > that definition must have an initialization clause.

> I don't think I missed that point.

Then I misunderstood your point.  The rule is "coherent": a
declaration of a reference must have an initializer if and only
if it is a definition.  (In some cases, the presense or absense
of the initializer determines whether it is a definition.)

I don't think that the rules are as coherent as they could be,
but the incoherence doesn't directly concern the requirement to
have an initializer or not.  In every case where the initializer
can be omitted, if it is omitted, the declaration is not a
definition.

> That was my point.  It's a peculiar, seemingly arbitrary
> special case for references.

I'm afraid that I still don't see a special case.  Exactly the
same rules apply to a const int: if the declaration is a
definition, then an initializer must be present.  And the only
way a declaration of a const int is not a definition is if the
declaration declares external linkage:

    int const           i1 ;    //  error, initialization required.
    extern int const    i2 ;    //  no initialization required.

In the case of a reference, we have the issue that even
references that acquire their external linkage implicitly
require initialization:

    int&                ri ;    //  error, initialization required,
                                //  because this is a definition.

If there is an incoherence, it is that const objects and
references to const implicitly have internal linkage, whereas
the same declaration without the const has external linkage.
But this incoherence affects both objects and references.

> The way a not explicitly "extern" reference declaration is a
> definition is similar to how a not explicitly "extern"
> constant declaration is a definition.  But the way such a
> reference can have external linkage by default is different
> from constants.

Sort of.  But that's at least partially due to the fact that the
standard doesn't consider a reference an object, but rather
another name for an existing object.

> At namespace scope, we have

>     T& r = o;         // External linkage, definition because of type.
>     T* const p = &o;  // Internal linkage, definition because of type.

> One would expect, and I did originally expect, that when
> initialization is required, internal linkage is implied, but
> this special case breaks that expectation  --  for no good
> reason that I can see.

For the basic reason that initialization of a reference doesn't
mean at all the same thing that initialization of an object
does.  The initialization of a reference doesn't "initialize"
anything in memory, because references don't have to live in
memory.  It tells the compiler what the reference is an alias
for.

>From the point of view of the standard, of course.  I often
wonder if it wouldn't be clearer if the standard had taken the
approach that a reference is a constant, implicitly dereferenced
pointer, rather than to say that it is something entirely
different, but carefully defined so as to be compatible with a
constant, dereferenced pointer.  But the fact remains that
formally, initialization of a reference isn't so much the
initialization of a value as telling the compiler what the
reference aliases.  It's not what I would usually consider
initialization at all.

> Perhaps the best approach is to view constants as the special
> case.

They are.

> Or, come to think of it, to view both references and constants
> as special cases, which makes ordinary variables a third
> special case, so that all we have is a collection of special
> cases...

In sum, par for the course:-).

But I think that's really it.  There's no exception concerning
references and initialization, but three sets of rules
concerning which declarations are also definitions, and the
linkage of the declared names, one for references, one for const
objects, and one for non-const objects.  (Or maybe four sets:
references to const objects and references to non-const objects
have different rules.)

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Alf P. Steinbach" <alfps@start.no>
Date: Wed, 14 Jun 2006 11:35:05 CST
Raw View
* kanze:
>
>> It's a peculiar, seemingly arbitrary special case for references.
>
> I'm afraid that I still don't see a special case.  Exactly the
> same rules apply to a const int:

Nope (see below).


> if the declaration is a definition, then an initializer must be
 > present.

Formally that's backwards, because for a reference it's the initializer
that determines whether the declaration is a definition, not the other
way around.  Also, something that would be a reference definition if it
had an initializer, but doesn't have that, and isn't explicitly declared
'extern', is just malformed, it's not a definition.


[snip]
> If there is an incoherence, it is that const objects and
> references to const implicitly have internal linkage, whereas
> the same declaration without the const has external linkage.

In a way yes, but I think you're focusing on the wrong aspect, and that
way conjuring up a similarity that really isn't there.

The 'const' for something that a reference refers to is not a 'const'
for the reference itself.

The analogous case for non-reference would be a const pointer's linkage
being determined by the constness of what the pointer points to.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Wed, 14 Jun 2006 13:28:35 CST
Raw View
Alf P. Steinbach wrote:

> Formally that's backwards, because for a reference it's the initializer
> that determines whether the declaration is a definition, not the other
> way around.

It has nothing to do with whether the name being declared is a
reference, it has to do with whether the name being declared is
explicitly declared extern.

Any declaration with the extern keyword is also a definition if and
only if an explicit initializer is present.  Declarations without the
extern keyword are always definitions.  (I'm assuming we're just
talking about variable declarations; static data members, functions and
types follow...sigh...different rules.)

I wonder if some confusion is caused by the assumption that keyword
extern has no effect other than to give the declared name external
linkage.  This is a false assumption: it changes the meaning of the
declaration:

  int i;  // declares & defines i
  extern int j;  // declares but doesn't define j

Both i and j have external linkage.  "extern" says both (1) give this
name external linkage and (2) treat this as a definition if and only if
I provide an explicit initializer.

> The 'const' for something that a reference refers to is not a 'const'
> for the reference itself.
>
> The analogous case for non-reference would be a const pointer's linkage
> being determined by the constness of what the pointer points to.


I think that is a mis-perception that comes from thinking of references
as automatically dereferenced pointers, rather than as what the
standard says they are: pure aliases.  Consider:

   const int a = 0;
   const int& b = a;

"a" names a const object.  "b" also names a const object (as it
happens, the same one).  They're alike.  It's non-sensical to think of
"b" as naming "the reference", because no such object exists to name.

(Of course, in some situations, the implementation will use a pointer
"under the hood," e.g. for reference members.  But that's an
implementation detail, irrelevant to the *concept* of references.)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: alfps@start.no ("Alf P. Steinbach")
Date: Wed, 14 Jun 2006 20:25:43 GMT
Raw View
* johnchx2@yahoo.com:
> Alf P. Steinbach wrote:
>
>> Formally that's backwards, because for a reference it's the initializer
>> that determines whether the declaration is a definition, not the other
>> way around.
>
> It has nothing to do with whether the name being declared is a
> reference, it has to do with whether the name being declared is
> explicitly declared extern.
>
> Any declaration with the extern keyword is also a definition if and
> only if an explicit initializer is present.

How is that different from what I wrote?


>  Declarations without the
> extern keyword are always definitions.  (I'm assuming we're just
> talking about variable declarations; static data members, functions and
> types follow...sigh...different rules.)

Well, a reference isn't a variable, so that's not what we're talking about.


> I wonder if some confusion is caused by the assumption that keyword
> extern has no effect other than to give the declared name external
> linkage.  This is a false assumption: it changes the meaning of the
> declaration:
>
>   int i;  // declares & defines i
>   extern int j;  // declares but doesn't define j
>
> Both i and j have external linkage.  "extern" says both (1) give this
> name external linkage and (2) treat this as a definition if and only if
> I provide an explicit initializer.
>
>> The 'const' for something that a reference refers to is not a 'const'
>> for the reference itself.
>>
>> The analogous case for non-reference would be a const pointer's linkage
>> being determined by the constness of what the pointer points to.
>
> I think that is a mis-perception

What is a mis-perception, do you think?


> that comes from thinking of references
> as automatically dereferenced pointers, rather than as what the
> standard says they are: pure aliases.  Consider:
>
>    const int a = 0;
>    const int& b = a;
>
> "a" names a const object.  "b" also names a const object (as it
> happens, the same one).  They're alike.  It's non-sensical to think of
> "b" as naming "the reference", because no such object exists to name.

In order to declare 'b' as an 'extern' reference you need to be aware
that it's a reference, and declare it in other translation units as a
reference.

I don't think the standard is non-sensical here.

I think the only sensible way to think of 'b' is as a reference.

For the purpose of 'extern', which is what this tread is all about, it
won't do to treat 'b' as simply an alternate name for an object.

'extern const int b;' in some other translation unit does not refer to
'extern const int& b = a' in this one.


> (Of course, in some situations, the implementation will use a pointer
> "under the hood," e.g. for reference members.  But that's an
> implementation detail, irrelevant to the *concept* of references.)

Details matter, understanding the implementation matters, and yes,
concepts matter: none of it is irrelevant.


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Fri, 2 Jun 2006 21:04:57 CST
Raw View
Alf P. Steinbach wrote:
> I am assuming a reference declared at namespace scope without 'extern'
> has internal linkage, no matter whether it refers to a const or
> non-const object, but I can't find any wording in the standard that
> directly backs up that assumption.
>
> A namespace scope reference must be initialized unless it's explicitly
> declared as 'extern', and to me that vaguely implies that otherwise it
> has internal linkage.
>
> Is there a solid answer to be found?

Certainly. If it is explicitly declared const, such a reference is
covered by 3.5, p3:

"A name having namespace scope (3.3.5) has internal linkage if it is
the name of
.
-- an object or reference that is explicitly declared const, and
neither explicitly delcared extern nor previously declared to have
external linkage;"

If not declared const, then it's covered by 3.5p4:

"A name having namespace scope has external linkage if it is the name
of
-- an object or reference, unless it has internal linkage"

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Dennett <jdennett@cox.net>
Date: Fri, 2 Jun 2006 23:17:44 CST
Raw View
kuyper@wizard.net wrote:
> Alf P. Steinbach wrote:
>> I am assuming a reference declared at namespace scope without 'extern'
>> has internal linkage, no matter whether it refers to a const or
>> non-const object, but I can't find any wording in the standard that
>> directly backs up that assumption.
>>
>> A namespace scope reference must be initialized unless it's explicitly
>> declared as 'extern', and to me that vaguely implies that otherwise it
>> has internal linkage.
>>
>> Is there a solid answer to be found?
>
> Certainly. If it is explicitly declared const, such a reference is
> covered by 3.5, p3:
>
> "A name having namespace scope (3.3.5) has internal linkage if it is
> the name of
> ..
> -- an object or reference that is explicitly declared const, and
> neither explicitly delcared extern nor previously declared to have
> external linkage;"

Interesting.  It is, of course, not legal to declare
a reference to be const (as references are by their
very nature immutable).

int three(3)
int & const ref(three); // compile-time error

Presumably this is intended to cover a reference-to-const
type?

-- James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: alfps@start.no ("Alf P. Steinbach")
Date: Sat, 3 Jun 2006 14:30:15 GMT
Raw View
* kuyper@wizard.net:
> Alf P. Steinbach wrote:
>> I am assuming a reference declared at namespace scope without 'extern'
>> has internal linkage, no matter whether it refers to a const or
>> non-const object, but I can't find any wording in the standard that
>> directly backs up that assumption.
>>
>> A namespace scope reference must be initialized unless it's explicitly
>> declared as 'extern', and to me that vaguely implies that otherwise it
>> has internal linkage.
>>
>> Is there a solid answer to be found?
>=20
> Certainly. If it is explicitly declared const, such a reference is
> covered by 3.5, p3:
>=20
> "A name having namespace scope (3.3.5) has internal linkage if it is
> the name of
> .
> -- an object or reference that is explicitly declared const, and
> neither explicitly delcared extern nor previously declared to have
> external linkage;"
>=20
> If not declared const, then it's covered by 3.5p4:
>=20
> "A name having namespace scope has external linkage if it is the name
> of
> -- an object or reference, unless it has internal linkage"

Thanks, this goes to show that it's possible to be cognitively blind=20
even if the eyes work all right (or almost).

But now it seems the standard has a rather arbitrary requirement:

   * If a reference has external linkage because it's explicitly
     declared 'extern', the initializer can be omitted (=A78.5.3/3, "The
     initializer can be omitted only ... where the extern specifier is
     explicitly used").

   * If, OTOH., a reference has external linkage because it doesn't
     refer to const and hasn't been declared 'static', the initializer
     cannot be omitted.

So the requirement to initialize locally hinges not on the effective=20
linkage of the reference, i.e. on whether the intent is to initialize it=20
once, in some translation unit, but on precisely how it acquired=20
external linkage, which, as I see it, doesn't matter at all wrt. safety=20
or correctness or any sound criterion for a local initialization=20
requirement, and is inconsistent with the requirements for other types.

--=20
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Tue, 6 Jun 2006 10:35:54 CST
Raw View
"Alf P. Steinbach" wrote:
> * kuyper@wizard.net:
> > Alf P. Steinbach wrote:
> >> I am assuming a reference declared at namespace scope
> >> without 'extern' has internal linkage, no matter whether it
> >> refers to a const or non-const object, but I can't find any
> >> wording in the standard that directly backs up that
> >> assumption.

> >> A namespace scope reference must be initialized unless it's
> >> explicitly declared as 'extern', and to me that vaguely
> >> implies that otherwise it has internal linkage.

> >> Is there a solid answer to be found?

> > Certainly. If it is explicitly declared const, such a
> > reference is covered by 3.5, p3:

> > "A name having namespace scope (3.3.5) has internal linkage
> > if it is the name of
> > .
> > -- an object or reference that is explicitly declared const, and
> > neither explicitly delcared extern nor previously declared to have
> > external linkage;"

> > If not declared const, then it's covered by 3.5p4:

> > "A name having namespace scope has external linkage if it is the name
> > of
> > -- an object or reference, unless it has internal linkage"

> Thanks, this goes to show that it's possible to be cognitively
> blind even if the eyes work all right (or almost).

> But now it seems the standard has a rather arbitrary requirement:

>    * If a reference has external linkage because it's explicitly
>      declared 'extern', the initializer can be omitted (   8.5.3/3, "The
>      initializer can be omitted only ... where the extern specifier is
>      explicitly used").

>    * If, OTOH., a reference has external linkage because it doesn't
>      refer to const and hasn't been declared 'static', the initializer
>      cannot be omitted.

> So the requirement to initialize locally hinges not on the
> effective linkage of the reference, i.e. on whether the intent
> is to initialize it once, in some translation unit, but on
> precisely how it acquired external linkage, which, as I see
> it, doesn't matter at all wrt. safety or correctness or any
> sound criterion for a local initialization requirement, and is
> inconsistent with the requirements for other types.

Not really.  You're missing another important point: which
declarations are in fact definitions.  A reference at namespace
scope which is not declared extern (or a reference with an
initialization, even if it is declared extern) is a definition.
There can only be one definition of the reference in the entire
program (or else you have undefined behavior -- and typically,
an error from the linker), and that definition must have an
initialization clause.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Alf P. Steinbach" <alfps@start.no>
Date: Fri, 2 Jun 2006 09:47:20 CST
Raw View
I am assuming a reference declared at namespace scope without 'extern'
has internal linkage, no matter whether it refers to a const or
non-const object, but I can't find any wording in the standard that
directly backs up that assumption.

A namespace scope reference must be initialized unless it's explicitly
declared as 'extern', and to me that vaguely implies that otherwise it
has internal linkage.

Is there a solid answer to be found?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]