ronen@cit-vax.Caltech.Edu (Ronen Barzel) (03/22/90)
C++ does not seem to allow "internal linkage" for member functions.
Am I wrong -- is there a way to do it? (If there isn't, IMHO there should be.)
Lippman sec 3.9 "static Global Variable" says:
"A global identifier preceded by the keyword 'static' will be
invisible outside the file in which it is defined... Static
identifiers at file scope are spoken of has having _internal_linkage_."
Preceding a declaration of a member function with 'static' isn't
covered by this. If I try it, cfront gives an error
"static specified for qualified name foo()"
-Ronen
[To answer the obvious question "why would you ever want to do that?",
I'll describe the scenario in which I want it:
I am writing a file to be included in a library; the file
defines some user-callable functions. Within that file,
I declare a class with member functions; the class is only
used internally by the library routines -- the user knows
nothing about it. Unfortunately, the mangled member function
names get entered into the .o as global symbols.
// foo.H -- header file for "foo" library
extern void public_foo();
// foo.C -- implements "foo" library
#include "foo.H"
class internal {
public: func();
}
internal::func() // want this to be 'static'
{
// ...
}
void public_foo()
{
internal x;
x.func();
// ...
}
The symbol table for foo.o includes two global text symbols:
"public_foo__Fv" (the one I want) and "func__8internalFv" (the
one I want to get rid of). I have two problems with this:
1. I can't use the same class & member names in more than one
file in the library. (A different file might want to define
a different 'internal' class with member function 'func'.)
2. The extra symbols clutter up the .o file; aside from
being aestheticaly unappealing, on a large scale it will
lead to slower link times, etc.
(Yes, the unwanted symbol can be removed via "ld -r -h func__8internalFv"
or whatever is analogous on your platform, but that's sort of ugly.)
]pcg@rupert.cs.aber.ac.uk (Piercarlo Grandi) (03/26/90)
In article <14373@cit-vax.Caltech.Edu> ronen@cit-vax.Caltech.Edu (Ronen Barzel) writes: C++ does not seem to allow "internal linkage" for member functions. Uh uh. Another guy that does not consistently follow my advice. Sorry, you are going to receive soon a call from who-you-know... :-) Given my all important and previous advice (:->) that member functions be *always* defined _after_ the class definition (in which only member functions declarations should appear), and that the storage class be *always* explicit in C++, you can write for example: struct c { int i; int m(int = 0); }; to *declare* 'm' and static int m (auto int j) { return this->i*j; } to *define* it with stoarage class static, that is internal linkage. The C++ compiler must not assume that the declaration of a member function implies external linkage, because there is no way to specify it in a member function declaration. Of course, if C++ did away entirely with the useless and confusing notion of member functions, or at least did not allow them to be declared inside the class definition, many problems like this would be immensely clarified or disappear altogether. -- Piercarlo "Peter" Grandi | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcvax!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk
ark@alice.UUCP (Andrew Koenig) (03/27/90)
In article <PCG.90Mar25214938@rupert.cs.aber.ac.uk>, pcg@rupert.cs.aber.ac.uk (Piercarlo Grandi) writes: > Given my all important and previous advice (:->) that member functions > be *always* defined _after_ the class definition (in which only member > functions declarations should appear), and that the storage class be > *always* explicit in C++, you can write for example: > struct c { int i; int m(int = 0); }; > to *declare* 'm' and > static int m (auto int j) { return this->i*j; } > to *define* it with stoarage class static, that is internal linkage. Indeed. But the second `m' you have defined here has nothing to do with the first. In fact, if you try compiling the example above, you will find that cfront says error: ``this'' used in non class context On the other hand, if you make it plain that the second `m' is an attempt to define the first: struct c { int i; int m(int = 0); }; static int c::m (auto int j) { return this->i*j; } you will find that indeed you cannot say `static' for a member function: error: static specified for qualified name m() -- --Andrew Koenig ark@europa.att.com
pcg@rupert.cs.aber.ac.uk (Piercarlo Grandi) (03/28/90)
In article <10628@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
On the other hand, if you make it plain that the second `m'
is an attempt to define the first:
struct c { int i; int m(int = 0); };
static int c::m (auto int j) { return this->i*j; }
Yes, a typo. Even I do typos occasionally, ok? :-).
you will find that indeed you cannot say `static' for a member function:
error: static specified for qualified name m()
Shame on cfront. G++ gets it "right". I only have Lippman as far as 2.0
goes, but I am at a loss to find a specific prohibition. And if it is
in the Ugly Red Book, shame on it as well. :-).
There is of course another course/curse :->; one can declare the member
function inline which implies static/internal linkage. If it is suitably
large cfront will refuse to actually inline it, and so you "win" :-(.
Bleah.
--
Piercarlo "Peter" Grandi | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth | UUCP: ...!mcvax!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk