Topic: ??? static locals in inline functions ???
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/07 Raw View
damian@molly.cs.monash.edu.au (Damian Conway) writes:
>fjh@munta.cs.mu.OZ.AU (Fergus Henderson) writes:
>
>>The reason is that an inline function by default has static linkage,
>>and so each translation unit gets its own copy.
>
>Is this the case for class function members
>(which are automatically inlined)?
No. Member functions of a class always have external linkage (unless
the class is a local class declared inside a function).
So there should always be only one occurrence of a static variable
declared inside a class member function.
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/08 Raw View
kaelin@bridge.com (Kaelin Colclasure) writes:
>Dick Menninger <Dick.Menninger@DaytonOH.ATTGIS.COM> writes:
>
> Dick> A better way to look at this is to see that inline
> Dick> behaves like const as they both default to internal scope.
> Dick> I suspect this choice comes from applicability to member
> Dick> functions. If you made inline default to external scope,
> Dick> you would have difficulty changing that to internal scope
> Dick> for member functions. Attaching static would have a rather
> Dick> different semantics. However, having inline default to
> Dick> internal scope allows extern to be applied without a change
> Dick> of class-level semantics of the function.
There has been some confusion of the three distinct concepts of scope
(visibility), access, and linkage in this thread. Everywhere that Dick
Menninger refers to "scope", he should be referring to "linkage".
Roughly speaking, the distinction is as follows.
Scope determines which name an identifier refers to.
Linkage determines whether different occurrences of the same name
(e.g. in different translation units) refer to the same entity.
Access determines when it is legal for a particular name to
be used.
>Hmmm, I don't really understand how member functions enter into the
>picture here. The visibility of member functions is determined a) by
>the visibility of their enclosing class and b) by the explicit
>public/protected/private visibility tag they are assigned.
No, public/protected/private affect accessibility, not visibility.
The two are different concepts in C++.
>The concept of an "extern" member function is meaningless--
The concept of a member function with "extern" scope would be meaningless,
but the concept of a member function having external linkage is quite
meaningful. Indeed, all member functions have external linkage, except
for member functions of local classes defined withing other functions,
which have no linkage.
>Your example of const variables defaulting to "file scope" is
>something of a surprise to me as well.
s/file scope/internal linkage/
>I recognize the obvious
>benefit from a code generation perspective, but if this is true do we
>ever expect anyone to learn this language (C++) without first
>assimilating a massive body of historical and practical knowledge from
>which to draw insight as to why these inconsistancies exist?
I can't speak for anyone else, but I don't. I expect most people will
learn some small subset of the language, and then muddle on.
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: kaelin@bridge.com (Kaelin Colclasure)
Date: 1995/11/08 Raw View
In article <DHou9J.L8t@falcon.daytonoh.attgis.com>
Dick Menninger <Dick.Menninger@DaytonOH.ATTGIS.COM> writes:
>> ==========Kaelin Colclasure, 11/5/95==========
>>
>>
>> Thanks for the clarification! I wonder, though, if this isn't
>> something of a gratuitious inconsistancy. For all other
>> function definitions, extern is the default-- you have to use
>> the static keyword to restrict the definition to file scope.
>> Now the draft is saying that inline functions get exactly the
>> *opposite* semantics (ie. static is assumed, extern must be
>> declared explicitly).
>>
>> The only reason I can fathom for this is for compatibility with
>> existing, pre-standard C++ code-- and I'd say that's a pretty
>> weak basis given my intuition that this usage in existing
>> implementations should be pretty rare. Am I just missing
>> something? -- // Kaelin Colclasure
Dick> A better way to look at this is to see that inline
Dick> behaves like const as they both default to internal scope.
Dick> I suspect this choice comes from applicability to member
Dick> functions. If you made inline default to external scope,
Dick> you would have difficulty changing that to internal scope
Dick> for member functions. Attaching static would have a rather
Dick> different semantics. However, having inline default to
Dick> internal scope allows extern to be applied without a change
Dick> of class-level semantics of the function.
Hmmm, I don't really understand how member functions enter into the
picture here. The visibility of member functions is determined a) by
the visibility of their enclosing class and b) by the explicit
public/protected/private visibility tag they are assigned. The
concept of an "extern" member function is meaningless-- all member
functions are implicitly visible from any "file scope" providing that
the language's visibility criteria outlined above are satisfied. This
is why "static" can be safely overloaded in the context of a class
declaration as it is.
Indeed, as another respondant pointed out, my example inline function
when declared within a class scope would be treated as though it had
the extern keyword added implicitly. So this just reinforces my
intuition that the "current working paper" has this exactly
backwards.
Your example of const variables defaulting to "file scope" is
something of a surprise to me as well. I recognize the obvious
benefit from a code generation perspective, but if this is true do we
ever expect anyone to learn this language (C++) without first
assimilating a massive body of historical and practical knowledge from
which to draw insight as to why these inconsistancies exist?
Not that I'm implying this is all your fault, Dick. ;-)
--
// Kaelin Colclasure -------------------------------------------------------
// EMail: kaelin@bridge.com Mail: Bridge Information Systems, Inc.
// Voice: (314)567-8463 717 Office Parkway
// Fax: (314)432-5391 St. Louis, MO 63141
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: kaelin@bridge.com (Kaelin Colclasure)
Date: 1995/11/09 Raw View
In article <9531214.21952@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus Hend
erson) writes:
[Good explanation of distinction between access/linkage/scope
elided...]
>> The concept of an "extern" member function is meaningless--
Fergus> The concept of a member function with "extern" scope
Fergus> would be meaningless, but the concept of a member function
Fergus> having external linkage is quite meaningful. Indeed, all
Fergus> member functions have external linkage, except for member
Fergus> functions of local classes defined withing other
Fergus> functions, which have no linkage.
This is exactly what I was trying to say, albiet using antiquated
terminology. :-)
>> Your example of const variables defaulting to "file scope" is
>> something of a surprise to me as well.
Fergus> s/file scope/internal linkage/
I was exposed to K&R C at a tender age-- I blame society.
>> I recognize the obvious benefit from a code generation
>> perspective, but if this is true do we ever expect anyone to
>> learn this language (C++) without first assimilating a massive
>> body of historical and practical knowledge from which to draw
>> insight as to why these inconsistancies exist?
Fergus> I can't speak for anyone else, but I don't. I expect
Fergus> most people will learn some small subset of the language,
Fergus> and then muddle on.
I had intended that last as a purely rhetorical question, but at the
rate things are going I agree. I suppose we should all take some
comfort from the fact that anyone who manages to understand all this
has excellent job security.
--
// Kaelin Colclasure -------------------------------------------------------
// EMail: kaelin@bridge.com Mail: Bridge Information Systems, Inc.
// Voice: (314)567-8463 717 Office Parkway
// Fax: (314)432-5391 St. Louis, MO 63141
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: Dick Menninger <Dick.Menninger@daytonoh.attgis.com>
Date: 1995/11/10 Raw View
> ==========Fergus Henderson, 11/8/95==========
>
>
> kaelin@bridge.com (Kaelin Colclasure) writes:
>
> >Dick Menninger <Dick.Menninger@DaytonOH.ATTGIS.COM> writes:
> >
> > Dick> A better way to look at this is to see that inline
> > Dick> behaves like const as they both default to internal scope.
> > Dick> I suspect this choice comes from applicability to member
> > Dick> functions. If you made inline default to external scope,
> > Dick> you would have difficulty changing that to internal scope
> > Dick> for member functions. Attaching static would have a rather
> > Dick> different semantics. However, having inline default to
> > Dick> internal scope allows extern to be applied without a change
> > Dick> of class-level semantics of the function.
>
> There has been some confusion of the three distinct concepts of scope
> (visibility), access, and linkage in this thread. Everywhere that Dick
> Menninger refers to "scope", he should be referring to "linkage".
>
>
> The concept of a member function with "extern" scope would be
> meaningless,
> but the concept of a member function having external linkage is quite
> meaningful. Indeed, all member functions have external linkage, except
> for member functions of local classes defined withing other functions,
> which have no linkage.
>
I should have done more "homework" and been more
careful on wording before replying. I was too focused
on getting posts to work instead of what I was saying.
If a class has external linkage, its member names have
external linkage (3.5.5 dominates). This means that a
static local in an inline member function behaves differently
than the default for a regular inline function (which still
has internal linkage by default). Further, there is no way
to get the behavior of inline member functions to match
the default behavior for regular inline functions. This is
no great loss, except in the area of understandability
of the language. So much for naively plugging ideas
together and thinking you did something valid.
At least I got the inline "is like" const part right.
(as he flakes a little more rust off in a maximally
public way)
Good Day
Dick
Dick.Menninger@DaytonOH.ATTGIS.COM
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: kaelin@bridge.com (Kaelin Colclasure)
Date: 1995/11/03 Raw View
What behavior does the draft standard condone for the following
scenario:
1) In a header file, an inline function is defined to contain a local
static, like so:
inline int *
foo()
{
static int i;
return &i;
}
2) Two seperate modules include this header file, call them A and B.
A "initializes" foo():
#include "foo.h"
...
*foo() = 1;
...
3) B calls foo(), dereferences the pointer returned and prints its
value:
#include <iostream.h>
#include "foo.h"
...
cerr << "*foo() = " << *foo() << endl;
...
Some data points:
MSVC++: *foo() = 1
G++: *foo() = 0
Sun C++:*foo() = 0
CFront: "sorry, not implemented"
My intuition is that MSVC++ is doing the "right" thing (gasp), and what
"should" be the standard thing-- but I realize that the behavior I
want requires mangling a global variable name or the moral
equivalent. I want to know if the standard requires this or leaves
the behavior implementation defined...
--
// Kaelin Colclasure -------------------------------------------------------
// EMail: kaelin@bridge.com Mail: Bridge Information Systems, Inc.
// Voice: (314)567-8463 717 Office Parkway
// Fax: (314)432-5391 St. Louis, MO 63141
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: kaelin@bridge.com (Kaelin Colclasure)
Date: 1995/11/06 Raw View
In article <u9g2g5xbre.fsf@yorick.cygnus.com> jason@cygnus.com (Jason Merrill) writes:
>> What behavior does the draft standard condone for the following
>> scenario:
>> 1) In a header file, an inline function is defined to contain a
>> local static, like so:
>> 2) Two seperate modules include this header file, call them A
>> and B. A "initializes" foo():
>> 3) B calls foo(), dereferences the pointer returned and prints
>> its value:
>> Some data points:
>> MSVC++: *foo() = 1 G++: *foo() = 0 Sun C++:*foo() = 0
>> My intuition is that MSVC++ is doing the "right" thing (gasp),
>> and what "should" be the standard thing.
Jason> G++ and Sun conform to the current working paper for
Jason> this example. If foo had been explicitly declared 'extern
Jason> inline', or if it were a member function, MS would be
Jason> correct.
Thanks for the clarification! I wonder, though, if this isn't
something of a gratuitious inconsistancy. For all other function
definitions, extern is the default-- you have to use the static
keyword to restrict the definition to file scope. Now the draft is
saying that inline functions get exactly the *opposite* semantics
(ie. static is assumed, extern must be declared explicitly).
The only reason I can fathom for this is for compatibility with
existing, pre-standard C++ code-- and I'd say that's a pretty weak
basis given my intuition that this usage in existing implementations
should be pretty rare. Am I just missing something?
--
// Kaelin Colclasure -------------------------------------------------------
// EMail: kaelin@bridge.com Mail: Bridge Information Systems, Inc.
// Voice: (314)567-8463 717 Office Parkway
// Fax: (314)432-5391 St. Louis, MO 63141
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/06 Raw View
kaelin@bridge.com (Kaelin Colclasure) writes:
>What behavior does the draft standard condone for the following
>scenario:
>
>1) In a header file, an inline function is defined to contain a local
>static, like so:
>
> inline int *
> foo()
> {
> static int i;
> return &i;
> }
>
>2) Two seperate modules include this header file, call them A and B.
>A "initializes" foo():
>
> #include "foo.h"
> ...
> *foo() = 1;
> ...
>
>3) B calls foo(), dereferences the pointer returned and prints its
>value:
>
> #include <iostream.h>
> #include "foo.h"
> ...
> cerr << "*foo() = " << *foo() << endl;
> ...
>
>Some data points:
>
>MSVC++: *foo() = 1
>G++: *foo() = 0
>Sun C++:*foo() = 0
>CFront: "sorry, not implemented"
>
>My intuition is that MSVC++ is doing the "right" thing (gasp), and what
>"should" be the standard thing-- but I realize that the behavior I
>want requires mangling a global variable name or the moral
>equivalent. I want to know if the standard requires this or leaves
>the behavior implementation defined...
The standard mandates the behaviour of g++ and Sun C++.
The reason is that an inline function by default has static linkage,
and so each translation unit gets its own copy.
To get the behaviour exhibited by MSVC++ from a draft
standard-conforming compiler, you would have to explicitly declare foo() as
`extern'. That is, you would have to change the definition of foo() from
inline int * foo() { ... }
to
extern inline int * foo() { ... }
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]