Topic: Internal linkage (static, inline, un-ns)


Author: "Liam Fitzpatrick" <liam@iname.com>
Date: 1998/08/26
Raw View
markw65@my-dejanews.com wrote in message
<6rq2ko$pqi$1@nnrp1.dejanews.com>...
>In article <6rk0ca$ra3$1@news.indigo.ie>, Liam Fitzpatrick <liam@iname.com>
wrote:
--snip--
>> ---- foo.h ----
>> class foo
>> {
>>     friend void bar();
>>     // ... lots of interesting internals
>> };

--snip--
>> ---- barthief.cpp ----
>> #include "foo.h"
>
>> static void bar()
>> {
>>     // I know all about foo, but foo's author doens't know that!
>> }
>
>> ---- barthief2.cpp ----
>> #include "foo.h"
>
>> static void bar()
>> {
>>     // I know all about foo, but foo's author doens't know that!
>> }
>Fortunately, this is explicitly forbidden by the standard.

That was very wrong of me - my example code cannot work. The paper I
referred to used friend function templates, which work. Thanks Paul and Mark
for the corrections.

--snip--
>// iii)
>extern void baz();
>static void baz(); // illegal
>
>class Z { friend void fuz(); };
>static void fuz(); // illegal (same as iii)


The friend declaration does not introduce a new name into the namespace. Is
the second fuz() illegal, or does it just declare a different function? It
doesn't seem clear to me that it is exactly the same as (iii) as baz() with
external linkage was visible when an attempt was made to declare baz() with
internal linkage.

If it is illegal, does the same hold true for extern declarations at local
scope:
void cat()
{
    void dog();
}
static void dog();  // illegal?

I've been puzzled by this since seeing the example in 3.5 para 6 which shows
something which seems similar but is in the reverse order as legal.
static void f();
static int i = 0;                       //1
void g() {
    extern void f();                //  internal linkage
    int i;                          //2:  i  has no linkage
    {
        extern void f();        //  internal linkage
        extern int i;           //3: external linkage
    }
}

Liam



[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/08/27
Raw View
In article <35E21311.7D6F02E3@ix.netcom.com>,
  "Paul D. DeRocco" <pderocco@ix.netcom.com> wrote:
>
> Liam Fitzpatrick wrote:

> > Another possible reason is that static declarations allow strange
> > things to happen. One example is related to Scott Meyers discussion at
> > C++ World. In it he gives an example based on friendship like:

> > ---- foo.h ----
> > class foo
> > {
> >     friend void bar();
> >     // ... lots of interesting internals
> > };

> > ---- bar.cpp ----
> > #include "foo.h"

> > void bar()
> > {
> >     // foo's author knows that I know about foo
> > }

> > ---- barthief.cpp ----
> > #include "foo.h"

> > static void bar()
> > {
> >     // I know all about foo, but foo's author doens't know that!
> > }

> > If static was not available then only one void bar() function would be
> > allowed.

> According to the last draft, the above code is illegal. ...

[ moderator's note: excessive quoting deleted. -sdc ]

> Of course, barthief.cpp could put "static void bar();" prior to
> including "foo.h", but there's all sorts of mischief that you can
> accomplish by putting stuff before the #include directives. It is
> therefore normal coding practice never to put anything before the
> #includes except maybe some #defines.

bazthief.cpp could also gain access to all of foo's data without
bothering with bar:
    #define class struct
    #define private public
    #define protected public
    #include "foo.h"
    void baz()
    {
        // Doesn't steal name bar, but has full access anyway.
        // Friend? We don' need no stinkin' friends!
    }
One of the earliest and most consistent C++ philosophies is
that C++ prevents mistakes, but not fraud. None of the above
code can happen by accident.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp   Create Your Own Free Member Forum


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1998/08/28
Raw View
AllanW@my-dejanews.com wrote:
..
> bazthief.cpp could also gain access to all of foo's data without
> bothering with bar:
>     #define class struct
>     #define private public
>     #define protected public
>     #include "foo.h"
>     void baz()
>     {
>         // Doesn't steal name bar, but has full access anyway.
>         // Friend? We don' need no stinkin' friends!
>     }
> One of the earliest and most consistent C++ philosophies is
> that C++ prevents mistakes, but not fraud. None of the above
> code can happen by accident.

That trick is not guaranteed to work. According to the "One definition
rule", if a class type D is defined in multiple  translation units,
"each definition of D shall consist of the same sequence  of  tokens".
Therefore, a program which linked that translation unit with another
translation unit which did not play the same tricks, would be
ill-formed. As a practical matter, the name mangling used for the
different class definitions might be incompatible.


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/08/22
Raw View
Andrew Tomazos wrote:
>
> I want to specify a global function to have internal linkage to a
> translation unit.
>
> 1. Why is static deprecated as a means of specifying internal function
> linkage?
>
> static f() { ... }
> // static is deprecated last I heard.

Probably because the meaning of the word "static" is misleading.

> 2. Are functions defined in the unnamed namespace required to have
> prototypes declared, and are they defined as having internal linkage?
>
> namespace { f() { ... } }
> // I currently get, "function requires prototype error".

Could it be that the compiler is complaining about the lack of a return
type? I don't think it's _ever_ required that you declare a function
separately from defining it.

> 3. Are global inline functions specified as having internal, external
> or undefined linkage by the standard?  Do they require a prototype
> declaration?

According to CD2, the "inline" keyword has no effect on linkage. Unless
otherwise specified, a global inline function has external linkage.

> inline f() { ... }
> // I may not want the function inlined and some compilers
> // will give this external linkage anyway.
>
> 4. Are there any other ways to specify internal linkage?

Not that I can think of.

--

Ciao,
Paul


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1998/08/23
Raw View
On 22 Aug 1998 16:53:51 GMT, Liam Fitzpatrick <liam@iname.com> wrote:

>If static was not available then only one void bar() function would be
>allowed. If they were inline each void bar() would have to contain the same
>tokens. Any void bar() in an unnamed namespace would not be a friend. The
>program would be restricted to one void bar() function which is a friend of
>class foo.

Excellent point here.

Interestingly, this is one reason Lakos gives for avoiding long
distance friendship -- that is, making a class defined in one file
a friend to a class defined in another file.  The problem is that
two classes gain access to the internals of the central class,
whereas only one is supposed to.

In any case, Lakos' other reason for not using long distance
friendship still holds: it may make your code harder to maintain.
This is just a guideline, of course.  Long distance friendship
may be appropriate at times.


--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: jkanze@otelo.ibmmail.com
Date: 1998/08/25
Raw View
In article <35DCE4E5.914846FF@ix.netcom.com>,
  "Paul D. DeRocco" <pderocco@ix.netcom.com> wrote:
>
> Andrew Tomazos wrote:
> >
> > I want to specify a global function to have internal linkage to a
> > translation unit.
> >
> > 1. Why is static deprecated as a means of specifying internal functio=
n
> > linkage?
> >
> > static f() { ... }
> > // static is deprecated last I heard.
>
> Probably because the meaning of the word "static" is misleading.

And overused.  In the end, there is a limit to what you can do with it.

In the case of C++, there is the additional problem (as compared to C)
that not only objects, but also types have linkage.  And there was no way of
saying that a type (e.g. a user defined class) had no linkage; adding
static in front of a class definition means that any objects declared
in that declaration are also static.

Before namespaces, all class names had global linkage.  Thus, if in my
implementation code, I defined a class MyHelper in the implementation
file, and another person did the same, there was a naming conflict.

--
James Kanze    +33 (0)1 39 23 84 71    mailto: kanze@gabi-soft.fr
        +49 (0)69 66 45 33 10    mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient=E9e objet --
              -- Beratung in objektorientierter Datenverarbeitung

-----=3D=3D Posted via Deja News, The Leader in Internet Discussion
=3D=3D=
-----
http://www.dejanews.com/rg_mkgrp.xp   Create Your Own Free Member Forum


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/08/25
Raw View
Liam Fitzpatrick wrote:
>
> Another possible reason is that static declarations allow strange
> things to happen. One example is related to Scott Meyers discussion at
> C++ World. In it he gives an example based on friendship like:
>
> ---- foo.h ----
> class foo
> {
>     friend void bar();
>     // ... lots of interesting internals
> };
>
> ---- bar.cpp ----
> #include "foo.h"
>
> void bar()
> {
>     // foo's author knows that I know about foo
> }
>
> ---- barthief.cpp ----
> #include "foo.h"
>
> static void bar()
> {
>     // I know all about foo, but foo's author doens't know that!
> }
>
> If static was not available then only one void bar() function would be
> allowed.

According to the last draft, the above code is illegal. 7.1.1 [dlc.stc]
paragraph 7 says:

  The  linkages  implied  by  successive declarations for a given entity
  shall agree.  That is, within a given scope, each declaration  declar-
  ing  the  same  object name or the same overloading of a function name
  shall imply the same linkage.  [Example:
          static char* f(); // f() has internal linkage
          char* f()         // f() still has internal linkage
              { /* ... */ }
          char* g();        // g() has external linkage
          static char* g()  // error: inconsistent linkage
              { /* ... */ }
   --end example]

Also, 11.4 [class.friend] paragraph 3 says:

  A function first declared in a friend declaration has external linkage
  Otherwise, the function retains its previous linkage.

Of course, barthief.cpp could put "static void bar();" prior to
including "foo.h", but there's all sorts of mischief that you can
accomplish by putting stuff before the #include directives. It is
therefore normal coding practice never to put anything before the
#includes except maybe some #defines.

--

Ciao,
Paul


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: markw65@my-dejanews.com
Date: 1998/08/25
Raw View
In article <6rk0ca$ra3$1@news.indigo.ie>,
  Liam Fitzpatrick <liam@iname.com> wrote:

> Martin von Loewis wrote in message ...
> >andrew@stairways.com.au (Andrew Tomazos) writes:
> >> 1. Why is static deprecated as a means of specifying internal function
> >> linkage?

> >> static f() { ... }
> >> // static is deprecated last I heard.

> >Not sure on the historical background, here. My interpretation is that
> >static has just too many meanings:

> Another possible reason is that static declarations allow strange things to
> happen. One example is related to Scott Meyers discussion at C++ World. In
> it he gives an example based on friendship like:

> ---- foo.h ----
> class foo
> {
>     friend void bar();
>     // ... lots of interesting internals
> };

> ---- bar.cpp ----
> #include "foo.h"

> void bar()
> {
>     // foo's author knows that I know about foo
> }

> ---- barthief.cpp ----
> #include "foo.h"

> static void bar()
> {
>     // I know all about foo, but foo's author doens't know that!
> }

> ---- barthief2.cpp ----
> #include "foo.h"

> static void bar()
> {
>     // I know all about foo, but foo's author doens't know that!
> }

> If static was not available then only one void bar() function would be
> allowed. If they were inline each void bar() would have to contain the same
> tokens. Any void bar() in an unnamed namespace would not be a friend.  The
> program would be restricted to one void bar() function which is a friend of
> class foo.

Fortunately, this is explicitly forbidden by the standard. You cant
declare a
static friend function; you cant declare a previously declared static
function
as a friend, and you cant make a previously declared extern function
static.

eg

// i)
class X { static friend void foo(); }; // illegal

// ii)
static void bar();
class Y { friend void bar(); }; // illegal

// iii)
extern void baz();
static void baz(); // illegal

class Z { friend void fuz(); };
static void fuz(); // illegal (same as iii)

Mark Williams

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp   Create Your Own Free Member Forum


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: andrew@stairways.com.au (Andrew Tomazos)
Date: 1998/08/20
Raw View

I want to specify a global function to have internal linkage to a
translation unit.


1. Why is static deprecated as a means of specifying internal function
linkage?

static f() { ... }
// static is deprecated last I heard.


2. Are functions defined in the unnamed namespace required to have
prototypes declared, and are they defined as having internal linkage?

namespace { f() { ... } }
// I currently get, "function requires prototype error".


3. Are global inline functions specified as having internal, external or
undefined linkage by the standard?  Do they require a prototype
declaration?

inline f() { ... }
// I may not want the function inlined and some compilers
// will give this external linkage anyway.


4. Are there any other ways to specify internal linkage?






Regards,
Andrew.

--
Andrew Tomazos, Stairways Software.  Phone +61-8-9364-9879
<mailto:andrew@stairways.com.au> <http://www.stairways.com/>

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 1998/08/20
Raw View
andrew@stairways.com.au (Andrew Tomazos) writes:

> 1. Why is static deprecated as a means of specifying internal function
> linkage?
>
> static f() { ... }
> // static is deprecated last I heard.

Not sure on the historical background, here. My interpretation is that
static has just too many meanings:

static void f(){}  //static linkage
void f(){
  static int i;    //initialized on first usage, state survives invocations
}
class X{
  static int i;    //member state shared across all instances
}
int X::i;          //initialized at startup, still external linkage

Also, you still couldn't do classes whose members have static
linkage, instead of being static members.

> 2. Are functions defined in the unnamed namespace required to have
> prototypes declared, and are they defined as having internal
> linkage?

No, they are not different from other functions.
>
> namespace { f() { ... } }
> // I currently get, "function requires prototype error".

The error here is that a function without return type is not valid
C++.

>
> 3. Are global inline functions specified as having internal, external or
> undefined linkage by the standard?  Do they require a prototype
> declaration?

Footnote 79 says

>> The inline keyword has no effect on the linkage of a function.

So they have the linkage they'd if inline was not specified. Linkage
is always defined, the three choices are internal, external, or no
linkage. An inline function with no explicit linkage spec has external
linkage.

> 4. Are there any other ways to specify internal linkage?

[basic.link] says

>> A name having namespace scope (3.3.5) has internal linkage if it is
>> the name of
>> - an object, reference, function or function template that is
>>   explicitly declared static or,
>> - an object or reference that is explicitly declared const and
>>   neither explicitly declared extern nor previously declared to
>>   have external linkage; or
>> - a data member of an anonymous union.

Please note that members of anonymous namespaces have external
linkage. You just can't reference them from other translation units.

Hope this helps,
Martin


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Liam Fitzpatrick <liam@iname.com>
Date: 1998/08/22
Raw View
Martin von Loewis wrote in message ...
>andrew@stairways.com.au (Andrew Tomazos) writes:
>> 1. Why is static deprecated as a means of specifying internal function
>> linkage?
>>
>> static f() { ... }
>> // static is deprecated last I heard.
>
>Not sure on the historical background, here. My interpretation is that
>static has just too many meanings:


Another possible reason is that static declarations allow strange things to
happen. One example is related to Scott Meyers discussion at C++ World. In
it he gives an example based on friendship like:

---- foo.h ----
class foo
{
    friend void bar();
    // ... lots of interesting internals
};

---- bar.cpp ----
#include "foo.h"

void bar()
{
    // foo's author knows that I know about foo
}

---- barthief.cpp ----
#include "foo.h"

static void bar()
{
    // I know all about foo, but foo's author doens't know that!
}

---- barthief2.cpp ----
#include "foo.h"

static void bar()
{
    // I know all about foo, but foo's author doens't know that!
}

If static was not available then only one void bar() function would be
allowed. If they were inline each void bar() would have to contain the same
tokens. Any void bar() in an unnamed namespace would not be a friend. The
program would be restricted to one void bar() function which is a friend of
class foo.

Liam




      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]