[comp.lang.c++] internal linkage for member functions?

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