Topic: Defect Report: allow C language linkage type for static member function


Author: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/29
Raw View
David R Tribble <david@tribble.com> wrote:

> However, declaring an extern "C" static member function via a
> typedef seems to work on at least a few compilers:
>
>     extern "C"
>     {
>         typedef int     (CFunc)();       // extern C func
>         typedef int     (*CFuncPtr)();   // extern C func ptr
>     }
>
>     class Foo
>     {
>     public:
>         static CFunc    baz;     // extern C static member func
>     };
>
>     int Foo::baz()
>     {
>         return 23;
>     }
>
>     CFuncPtr    p = &Foo::baz;   // ptr to extern C func
>
> But is this legal ISO C++?

It's not legal ISO C++, because the Foo::baz member function ends up with
C++ language linkage type despite the fact that the CFunc typedef has C
language linkage type. Paragraph 7.5/4 of the standard says, "A C language
linkage is ignored for the names of class members and the member function
type of class member functions."

This the point of my DR. I suggested that the wording should be changed to
make it clear that static members are allowed to have C language linkage
type. Non-static members still won't have C language linkage type and no
member would ever have a C language linkage name.

Thus, the example above *would* be legal ISO C++ if the change suggested in
my DR was accepted.

    -- Darin
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/27
Raw View
Steve Clamage  <clamage@eng.sun.com> wrote:
>>    // function type with C language linkage
>>    extern "C" typedef void c_func();
>
> This syntax is not valid. You have to use brace notation:
>  extern "C" { typedef ... }

Are you sure? I can't find the rule you cite in the standard. Could you tell
me where to look?

Paragraph 7.5/3 says that a linkage-specification can be "extern
string-literal declaration" and I'm sure that a declaration can be a
typedef. The example in paragraph 7.5/4 includes typedefs that look just
like the one above, so either your compiler is wrong or the example in the
standard is wrong.

I think you may have found an error in the Sun C++ compiler rather than an
error in my code.

>>    // static member function that has C++ language linkage type, even
>>    // though we try to give it C language linkage type, because member
>>    // functions can never have C language linkage
>>    class D {
>>      public:
>>        static c_func cpp_func { }
>
> The definition of cpp_func is not valid. You cannot use a typedef
> for a function header.

The standard explicitly says that you can use a typedef for a declaration in
paragraph 8.3.5/7, "A typedef of function type may be used to declare a
function but shall not be used to define a function (8.4)." It then goes on
to give an example.

However, I tried to use a typedef to define a function, thus my example #2
must be modified (not discarded completely) as follows:

    ---- program #2 ----

    // function pointer with C language linkage
    extern "C" typedef void c_func();

    // function that takes a C language linkage function pointer
    void call(c_func* f) { (*f)(); }

    // static member function that has C++ language linkage type, even
    // though we try to give it C language linkage type, because member
    // functions can never have C language linkage
    class D {
      public:
        static c_func cpp_func;
    };
    void D::cpp_func() { }

    int main()
    {
        // attempt to pass C++ language linkage function pointer,
        // but the parameter is a C language linkage function pointer
        // thus its a type mismatch that should cause a diagnostic
        call(&D::cpp_func);
    }

> I don't believe it is possible to get the effect you want with #2 with any
> valid syntax, so it's a moot point. That is, I don't think it is possible to
> declare C linkage on a member function, static or not, under current language
> rules.

I believe I've provided evidence to the contrary above. I think that my
modified program #2 is correct other than the type mismatch.

    -- Darin
---
[ 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: comeau@panix.com (Greg Comeau)
Date: 1999/09/25
Raw View
In article <7sab1q$ubs@enews2.newsguy.com> "Darin Adler" <darin@bentspoon.com> writes:
>I wrote:
>> A thought on this point: I don't know of a single compiler that
>> correctly implements this rule yet that also distinguishes C and C++
>> function pointers as required by the standard.
>
>Greg Comeau <comeau@panix.com> wrote:
>> We (Comeau C++) kicks out both as well (including an option to accept
>> the former).  Darin, is there some sure bet problem example you are
>> thinking of?
>
>Perhaps you understood me perfectly, but I can't tell from your message. In
>case I wasn't clear enough about what I meant, I'll try to clarify.
>
>I wrote the above "thought" in response to William M. Miller's comment that,
>"by the five-year review time [...] most code will have been updated to
>reflect the requirements in the Standard." I wanted to point out that
>compilers don't yet follow this rule correctly, thus I had doubts that most
>code will be updated by the time of the five-year review. This is a minor
>point, and I didn't mean to belabor it.
>
>The comment was an observation that this particular pair of features aren't
>yet implemented in compilers that I have used:
>
>    1) distinguishing C and C++ language linkage function pointers
>    2) disallowing C language linkage for static member function type
>
>Here are some test programs to demonstrate. A conforming compiler is
>required to give an error or warning in the following program, because the
>type of the function pointer doesn't match.
>
>    ---- program #1 ----
>
>    // function type with C language linkage
>    extern "C" typedef void c_func();
>
>    // function that takes a C language linkage function pointer
>    void call(c_func* f) { (*f)(); }
>
>    // C++ language linkage function (both name and type)
>    void cpp_func() { }
>
>    int main()
>    {
>        // attempt to pass C++ language linkage function pointer,
>        // but the parameter is a C language linkage function pointer
>        // thus its a type mismatch that should cause a diagnostic
>        call(&cpp_func);
>    }
>
>Many current compilers don't distinguish C and C++ function pointers, so
>they accept the above program without an error, even in a "strict
>conforming" mode. The standard requires a diagnostic.

Comeau C++ should reject this.  As well, there is an option to accept it.

>Even among compilers that give a diagnostic for the program above, many do
>not implement the static member function rule correctly. The following
>program must also result in a diagnostic:
>
>    ---- program #2 ----
>
>    // function pointer with C language linkage
>    extern "C" typedef void c_func();
>
>    // function that takes a C language linkage function pointer
>    void call(c_func* f) { (*f)(); }
>
>    // static member function that has C++ language linkage type, even
>    // though we try to give it C language linkage type, because member
>    // functions can never have C language linkage
>    class D {
>      public:
>        static c_func cpp_func { }
>    };
>
>    int main()
>    {
>        // attempt to pass C++ language linkage function pointer,
>        // but the parameter is a C language linkage function pointer
>        // thus its a type mismatch that should cause a diagnostic
>        call(&D::cpp_func);
>    }

Comeau ++ should reject it for the same reason.

But, wait, isn't there another problem with cpp_func an illegal definition?
That is, you can declared a func through a TD but cannot define it with one.

>This program is legal, and should compile successfully:
>
>    ---- program #3 ----
>
>    // function pointer with C language linkage
>    extern "C" typedef void c_func();
>
>    // function that takes a C language linkage function pointer
>    void call(c_func* f) { (*f)();  }
>
>    // function with C++ language linkage name, but C language
>    // linkage type
>    c_func cpp_func;
>    void cpp_func() { }
>
>    int main()
>    {
>        // this should work
>        call(&cpp_func);
>    }

So it seems.

>My point was merely that compilers that will accept program #3 and reject
>both programs #1 and #2 are currently rare; I don't know of any.

See above :)

>In a message since, Michael Ball assured me that such compilers do exist and
>it's my experience that is narrow.

I don't know how all handle it, so I don't know.

>He gave the latest Sun compiler as an
>example; based on his remarks I expect that it handles all three of the
>above programs properly, although it's possible that I didn't make myself
>clear at the time and he was talking about something else.
>
>Perhaps compilers that get these two rules correct are more common than I
>had originally believed. I know that both Apple's MrC compiler and
>Metrowerks' CodeWarrior Pro 5 compiler incorrectly accept program #2 without
>a diagnostic, although MrC correctly diagnoses the problem in program #1.
>
>Francis Glassborow indicated that he and some others on the committee who
>added the rules about C and C++ language linkage expected many compilers to
>accept programs like program #1 as an extension, rejecting them only in
>"strictly conforming mode".

I wonder how much "the accepting as extension" gets in the way...

- Greg
--
       Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
     Producers of Comeau C/C++ 4.2.38 -- NOTE 4.2.42 BETAS NOW AVAILABLE
    Email: comeau@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
                *** WEB: http://www.comeaucomputing.com ***
---
[ 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: clamage@eng.sun.com (Steve Clamage)
Date: 1999/09/24
Raw View
"Darin Adler" <darin@bentspoon.com> writes:

>The comment was an observation that this particular pair of features aren't
>yet implemented in compilers that I have used:

>    1) distinguishing C and C++ language linkage function pointers
>    2) disallowing C language linkage for static member function type

>Here are some test programs to demonstrate. A conforming compiler is
>required to give an error or warning in the following program, because the
>type of the function pointer doesn't match.

>    ---- program #1 ----

>    // function type with C language linkage
>    extern "C" typedef void c_func();

This syntax is not valid. You have to use brace notation:
 extern "C" { typedef ... }

>    // function that takes a C language linkage function pointer
>    void call(c_func* f) { (*f)(); }

>    // C++ language linkage function (both name and type)
>    void cpp_func() { }

>    int main()
>    {
>        // attempt to pass C++ language linkage function pointer,
>        // but the parameter is a C language linkage function pointer
>        // thus its a type mismatch that should cause a diagnostic
>        call(&cpp_func);
>    }

>Many current compilers don't distinguish C and C++ function pointers, so
>they accept the above program without an error, even in a "strict
>conforming" mode. The standard requires a diagnostic.

>Even among compilers that give a diagnostic for the program above, many do
>not implement the static member function rule correctly. The following
>program must also result in a diagnostic:

>    ---- program #2 ----

>    // function pointer with C language linkage
>    extern "C" typedef void c_func();

Same problem with extern "C" as above.

>    // function that takes a C language linkage function pointer
>    void call(c_func* f) { (*f)(); }

>    // static member function that has C++ language linkage type, even
>    // though we try to give it C language linkage type, because member
>    // functions can never have C language linkage
>    class D {
>      public:
>        static c_func cpp_func { }

The definition of cpp_func is not valid. You cannot use a typedef
for a function header.

>    };

>    int main()
>    {
>        // attempt to pass C++ language linkage function pointer,
>        // but the parameter is a C language linkage function pointer
>        // thus its a type mismatch that should cause a diagnostic
>        call(&D::cpp_func);
>    }

>This program is legal, and should compile successfully:

>    ---- program #3 ----

>    // function pointer with C language linkage
>    extern "C" typedef void c_func();

>    // function that takes a C language linkage function pointer
>    void call(c_func* f) { (*f)();  }

>    // function with C++ language linkage name, but C language
>    // linkage type
>    c_func cpp_func;
>    void cpp_func() { }

>    int main()
>    {
>        // this should work
>        call(&cpp_func);
>    }

>My point was merely that compilers that will accept program #3 and reject
>both programs #1 and #2 are currently rare; I don't know of any.

Sun C++ for #1 (after correcting the syntax error)
emits an error message about the linkage mismatch.

I don't believe it is possible to get the effect you want with
#2 with any valid syntax, so it's a moot point. That is, I
don't think it is possible to declare C linkage on a member
function, static or not, under current language rules.

Sun C++ accepts #3 without complaint.


>Francis Glassborow indicated that he and some others on the committee who
>added the rules about C and C++ language linkage expected many compilers to
>accept programs like program #1 as an extension, rejecting them only in
>"strictly conforming mode".

Sun C++ treats the linkage mismatch as an "anachronism".
An "anachronism" is a warning that can be turned into an error
via a compiler option.

--
Steve Clamage, stephen.clamage@sun.com
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/23
Raw View
I wrote:
> A thought on this point: I don't know of a single compiler that
> correctly implements this rule yet that also distinguishes C and C++
> function pointers as required by the standard.

Greg Comeau <comeau@panix.com> wrote:
> We (Comeau C++) kicks out both as well (including an option to accept
> the former).  Darin, is there some sure bet problem example you are
> thinking of?

Perhaps you understood me perfectly, but I can't tell from your message. In
case I wasn't clear enough about what I meant, I'll try to clarify.

I wrote the above "thought" in response to William M. Miller's comment that,
"by the five-year review time [...] most code will have been updated to
reflect the requirements in the Standard." I wanted to point out that
compilers don't yet follow this rule correctly, thus I had doubts that most
code will be updated by the time of the five-year review. This is a minor
point, and I didn't mean to belabor it.

The comment was an observation that this particular pair of features aren't
yet implemented in compilers that I have used:

    1) distinguishing C and C++ language linkage function pointers
    2) disallowing C language linkage for static member function type

Here are some test programs to demonstrate. A conforming compiler is
required to give an error or warning in the following program, because the
type of the function pointer doesn't match.

    ---- program #1 ----

    // function type with C language linkage
    extern "C" typedef void c_func();

    // function that takes a C language linkage function pointer
    void call(c_func* f) { (*f)(); }

    // C++ language linkage function (both name and type)
    void cpp_func() { }

    int main()
    {
        // attempt to pass C++ language linkage function pointer,
        // but the parameter is a C language linkage function pointer
        // thus its a type mismatch that should cause a diagnostic
        call(&cpp_func);
    }

Many current compilers don't distinguish C and C++ function pointers, so
they accept the above program without an error, even in a "strict
conforming" mode. The standard requires a diagnostic.

Even among compilers that give a diagnostic for the program above, many do
not implement the static member function rule correctly. The following
program must also result in a diagnostic:

    ---- program #2 ----

    // function pointer with C language linkage
    extern "C" typedef void c_func();

    // function that takes a C language linkage function pointer
    void call(c_func* f) { (*f)(); }

    // static member function that has C++ language linkage type, even
    // though we try to give it C language linkage type, because member
    // functions can never have C language linkage
    class D {
      public:
        static c_func cpp_func { }
    };

    int main()
    {
        // attempt to pass C++ language linkage function pointer,
        // but the parameter is a C language linkage function pointer
        // thus its a type mismatch that should cause a diagnostic
        call(&D::cpp_func);
    }

This program is legal, and should compile successfully:

    ---- program #3 ----

    // function pointer with C language linkage
    extern "C" typedef void c_func();

    // function that takes a C language linkage function pointer
    void call(c_func* f) { (*f)();  }

    // function with C++ language linkage name, but C language
    // linkage type
    c_func cpp_func;
    void cpp_func() { }

    int main()
    {
        // this should work
        call(&cpp_func);
    }

My point was merely that compilers that will accept program #3 and reject
both programs #1 and #2 are currently rare; I don't know of any.

In a message since, Michael Ball assured me that such compilers do exist and
it's my experience that is narrow. He gave the latest Sun compiler as an
example; based on his remarks I expect that it handles all three of the
above programs properly, although it's possible that I didn't make myself
clear at the time and he was talking about something else.

Perhaps compilers that get these two rules correct are more common than I
had originally believed. I know that both Apple's MrC compiler and
Metrowerks' CodeWarrior Pro 5 compiler incorrectly accept program #2 without
a diagnostic, although MrC correctly diagnoses the problem in program #1.

Francis Glassborow indicated that he and some others on the committee who
added the rules about C and C++ language linkage expected many compilers to
accept programs like program #1 as an extension, rejecting them only in
"strictly conforming mode".

    -- Darin

PS: The example given by David Tribble that you quoted is unrelated.

David Tribble <david@tribble.com> wrote:
>The following resulted in a syntax error:
>
>    class Foo
>    {
>    public:
>        extern "C" static int bar();
>    };

The above declaration does contain a syntax error; every compiler I've tried
gets that right, and diagnoses the error.
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/21
Raw View
David R Tribble <david@tribble.com> wrote:

> So what is the proper syntax for declaring an extern C function
> as a friend to a class?
>
>     extern "C" int  foo();
>     extern "C" int  bar();
>
>     class Xyz
>     {
>         friend extern "C" int  foo();    // ?
>         friend            int  bar();    // ?
>         ...
>     };

There are many ways.

You can't have extern "C" after friend, so your foo() example won't work.
11.4/6 says, "No storage-class-specifier shall appear in the
decl-specifier-seq of a friend declaration."

Your bar() example will work. Standard 11.4/3 says, "A function first
declared in a friend declaration has external linkage. Otherwise, the
function retains its previous linkage (7.1.1)." This includes the language
linkage as well as internal vs. external linkage.

You can also do this:

    extern "C" {
        class Zyx {
            friend int bletch();
        };
    }

The function bletch() is a friend with C language linkage.

The extern "C" does affect things within the class definition, although it
doesn't affect the names of member functions or the types of non-static
member functions. If we start talking about how it affects the types of
static member functions, we're back to the beginning of the thread.

    -- Darin
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/17
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:

> You place it in the implementation file (which is why I declared it
> static so that it cannot leak out to the rest of your code).

It must be a friend, thus must be declared in the public header. Here's the
version where the forwarding function is static:

    --- header file ---

    // declare the forwarding function
    // must use the braces form of extern "C" because linkage
    // specifier is not allowed after extern "C"
    extern "C" { static int Foo_callback(int); }

    class Foo {
      private:
        // make the forwarding function a friend
        friend int Foo_callback(int);
        // here's the actual callback function
        static int callback(int);
    };

    --- implementation file ---

    // define the forwarding function
    // nothing prevents other functions with the same name from
    // being declared in other implementation files
    inline int Foo_callback(int x)
        { return Foo::callback(x); }

This creates a problem where anyone can declare a function named
Foo_callback to get access to callback(). The defeats the purpose of having
callback() be private.

    -- Darin

PS: No good reason for Foo_callback to be an inline function either.


[ 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: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/17
Raw View
In article <7rs3hk$2g3r@enews2.newsguy.com>, Darin Adler
<darin@bentspoon.com> writes
>This creates a problem where anyone can declare a function named
>Foo_callback to get access to callback(). The defeats the purpose of having
>callback() be private.

But access was never meant to prevent theft only to help detect
stupidity.  Anyone who chooses to provide their own definition of a
friend function deserves the consequences (I can think of many other
ways to invade privacy).

OK leave out the static qualification but still define in the
implementation file.  Now any alternative definition breaches the ODR.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/18
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:

> But access was never meant to prevent theft only to help detect stupidity.
> Anyone who chooses to provide their own definition of a friend function
> deserves the consequences (I can think of many other ways to invade privacy).

Granted.

But I often need to detect stupidity across a large program, worked on by
many people, some of them misguided. When looking for problems, it helps if
the compiler does the checking for me and I don't have to search myself.

> OK, leave out the static qualification but still define in the
> implementation file.  Now any alternative definition breaches the ODR.

Fixes one problem, causes another:

    --- header file ---

    class Foo {
      private:
        // make the forwarding function a friend
        friend int Foo_callback(int);
        // here's the actual callback function
        static int callback(int);
    };

    --- implementation file ---

    // define the forwarding function
    int Foo_callback(int x)
        { return Foo::callback(x); }

Now the function can be called from any implementation file that includes
the header. This case is mentioned in my original defect report: "These
alternatives expose more of a class's implementation than a static member
function; either the friend function itself is visible at namespace scope
alongside the class definition [...]"

    -- Darin


[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/15
Raw View
Michael Ball <ball@eng.sun.com> wrote:

> So don't put it into the header file!
> Then you can be quite sure that nobody calls it.

Then it can't be a friend. A static friend function must be declared
before the friend declaration, so it has to be in the header file.
That's what drove me toward a static member function in the first
place.

    -- Darin


[ 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: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/15
Raw View
In article <7rjqh4$27c6@enews4.newsguy.com>, Darin Adler
<darin@bentspoon.com> writes
>You (and others participating in the standard committees) should
>proceed with care. That's what I expect.
>
>You haven't said what these wider implications could be, so I can't
>help you address them (it's a bit unfair to be so vague). I hope that
>the committee will consider wider implications, if they are found,
>before making a change.

The problem is that this involves the type system and we know from
experience that modifications to this can have unexpected results.  If
we immediately knew what they were we would say.  Unfortunately
experience has taught some of us that no change to the type system is as
simple as we at first believe it will be.

I have to say that as long as there is a possible work-around that is
not too burdensome I would be very reluctant to fiddle with the type
system at this stage.  Use of a filescope static inline extern "C"
forwarding function (I think you are allowed to string all those
together) would seem to provide a work-around.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/15
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
> Use of a file scope static inline extern "C" forwarding function (I think
> you are allowed to string all those together) would seem to provide a
> work-around.

Wow! The best workaround yet! On further reflection, the forwarding
function doesn't need to be static, since inlines with external
linkage have suitable semantics.

    class foo {
      private:
        // make the forwarding function a friend
        friend int foo_Callback(int);
        // here's the actual callback function
        static int Callback(int);
    };

    // define the forwarding function as an inline function
    // this prevents others from (intentionally or inadvertently)
    // defining a function with the same to bypass accessibility
    extern "C" inline int foo_Callback(int x)
        { return foo::Callback(x); }

Thanks, Francis!

    -- Darin
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/16
Raw View
Darin Adler <darin@bentspoon.com> wrote:
> Wow! The best workaround yet! On further reflection, the forwarding
> function doesn't need to be static, since inlines with external
> linkage have suitable semantics.
>
>     class foo {
>       private:
>         // make the forwarding function a friend
>         friend int foo_Callback(int);
>         // here's the actual callback function
>         static int Callback(int);
>     };
>
>     // define the forwarding function as an inline function
>     // this prevents others from (intentionally or inadvertently)
>     // defining a function with the same to bypass accessibility
>     extern "C" inline int foo_Callback(int x)
>         { return foo::Callback(x); }

Oops! In my enthusiasm I didn't notice that foo_Callback is fully
accessible. The defeats the purpose of having Callback be private. Now
I have to search all the code that includes this header to see if
anyone (intentionally or inadvertently) is calling foo_Callback. It's
not enough just to look at the definitions of members of foo.

So the work-around isn't as great as I thought.

    -- Darin
---
[ 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: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/16
Raw View
In article <7rouju$s7e@enews3.newsguy.com>, Darin Adler
<darin@bentspoon.com> writes
>Oops! In my enthusiasm I didn't notice that foo_Callback is fully
>accessible. The defeats the purpose of having Callback be private. Now
>I have to search all the code that includes this header to see if
>anyone (intentionally or inadvertently) is calling foo_Callback. It's
>not enough just to look at the definitions of members of foo.
>
>So the work-around isn't as great as I thought.

You place it in the implementation file (which is why I declared it
static so that it cannot leak out to the rest of your code).


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ 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: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/13
Raw View
In article <7rfj4h$2dga@enews4.newsguy.com>, Darin Adler
<darin@bentspoon.com> writes
>I don't need a new feature for this. Declaring a function with C language
>linkage type does it. It's part of the standard language and doesn't require
>an extension. It just can't be used with static member functions, which was
>the point of my defect report.

OK.  Now my memory is that when we were discussing the change it was our
belief that where C and C++ linkage were compatible modulus name-
mangling that implementors would (perhaps through a compile time switch)
enable implicit conversion between pointers to extern "C" and extern
"C++" functions.

Now I think what you are asking for may have wider implications and I
think that we would need to proceed with care.  Note that I am not
rejecting it out of hand but the normal guidance is that if what you
need can be achieved by other means then the correction is not urgent.
I am open to being persuaded otherwise.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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: "Bill Wade" <bill.wade@stoner.com>
Date: 1999/09/13
Raw View
Darin Adler wrote in message <7r95ff$2bt0@enews3.newsguy.com>...
>If a static
>member function can't have a type with C language linkage, then a global or
>friend function must be used instead. These alternatives expose more of a
>class's implementation than a static member function; either the friend
>function itself is visible at namespace scope alongside the class
definition
>or the private member function must be made public so it can be called by a
>non-friend function.

I agree with the thrust of your DR.  It should be possible to make static
members extern "C" (calling protocal, but not for naming).

However there is a workaround that gives you most of the benefit.  You can
restrict the visibility of the "C" function to the class's implementation
file (I haven't compiled this.  Expect typos).

// foo.h
extern "C" typedef int c_func(int);
typedef int cpp_func(int);
class foo
{
private:
  c_func* GetCallback();
  static int Callback(int);
};

// foo.cpp
#include "foo.h"

// A local pointer to the static member that will handle the callback.
static cpp_func* cpp_callback=0;

// The C function that will actually get registered.
extern "C" int CFunk(int i)
{
  return cpp_callback(i);
}

c_func* foo::GetCallback()
{
  cpp_callback = &Callback;    // Only needs to be done once.
  return &CFunk;
}

HTH
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/14
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:

> Now my memory is that when we were discussing the change it was our belief
> that where C and C++ linkage were compatible modulus name- mangling that
> implementors would (perhaps through a compile time switch) enable implicit
> conversion between pointers to extern "C" and extern "C++" functions.

As you and I discussed in our private email exchange, this is not in
the standard. Compiler vendors may chose to provide this extension,
but there's nothing in the standard to urge them to do any particular
extension, this one included, and most of them were not privy to the
committee discussion you refer to.

You point out that this could be provided through a compile-time
switch. The same could be said about any non-standard change to the
language! If it's not provided through a compile-time switch any
conforming compiler must issue a diagnostic before doing an implicit
conversion as you suggest.

In our email, I used the analogy to "int*" vs. "long*". If int and
long have the same underlying representation in a particular
environment, then these pointers could be considered "compatible", but
I don't suggest that compilers allow mixing the two types. I feel the
same way about C and C++ language linkage type function pointers.

> Now I think what you are asking for may have wider implications and I
> think that we would need to proceed with care.

You (and others participating in the standard committees) should
proceed with care. That's what I expect.

You haven't said what these wider implications could be, so I can't
help you address them (it's a bit unfair to be so vague). I hope that
the committee will consider wider implications, if they are found,
before making a change.

> I am open to being persuaded otherwise.

I'm using both a compiler that works as I suggest and another that
works as the standard suggests. I considered the matter carefully
before writing my defect report.

I'd like to convince you that there aren't wider implications and that
this is a desirable change, but I've already done my best to do so.

    -- Darin
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/14
Raw View
Bill Wade <bill.wade@stoner.com> wrote:

> However there is a workaround that gives you most of the benefit.  You can
> restrict the visibility of the "C" function to the class's implementation
> file (I haven't compiled this.  Expect typos).
>
> // foo.h
> extern "C" typedef int c_func(int);
> typedef int cpp_func(int);
> class foo
> {
> private:
>   c_func* GetCallback();
>   static int Callback(int);
> };
>
> // foo.cpp
> #include "foo.h"
>
> // A local pointer to the static member that will handle the callback.
> static cpp_func* cpp_callback=0;
>
> // The C function that will actually get registered.
> extern "C" int CFunk(int i)
> {
>   return cpp_callback(i);
> }
>
> c_func* foo::GetCallback()
> {
>   cpp_callback = &Callback;    // Only needs to be done once.
>   return &CFunk;
> }

Thanks for the workaround suggestion, Bill.

It costs more than the alternative, -- two extra functions and a
global function pointer for each call-back function -- which is too
bad. It's considerably more complicated and hard to explain than what
I used before the C/C++ change to the standard.

But it's compatible with the current standard, it doesn't expose any
unnecessary implementation details, and it works!

    -- Darin
---
[ 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: David R Tribble <david@tribble.com>
Date: 1999/09/14
Raw View
Francis Glassborow wrote:
>
> Darin Adler <darin@bentspoon.com> writes
>> Suggested Resolution: Change the sentence in paragraph 4 of 7.5
>> [dcl.link] to: "A C language linkage is ignored for the names of
>> class members and the member function types of non-static class
>> member functions."  The example need not be changed because it
>> doesn't involve a static member function.
>
> The problem with this is that along with calling conventions we have
> scope information (class name or namespace) that gets stripped off by
> extern "C".  I seem to recall that when we were considering the issue
> of whether linkage was part of the function type (very late in the
> Standardisation process, though Josee Lajoie and I had been promoting
> it for several years) we came to the conclusion that all that could be
> done was a further level of indirection in which an extern "C" global
> function forwarded to the class static function.

Indeed.  Otherwise, you'd have to add verbiage to the standard to
address the ambiguities that will arise in code such as:

    class Foo
    {
    public:
        extern "C" static void  func();
    };

    class Bar
    {
    public:
        extern "C" static void  func();
    };

In many implementations, 'extern "C"' implies that name mangling does
not occur.  If both Foo::func() and Bar::func() are translated into
object symbols without name mangling, they could very well (and most
likely will on most real implementations) have the same symbolic name.
Finding good working in the standard to address such a possibility
might be difficult.

OTOH, the name mangling rule need not apply for static members;
an extern "C" linkage in these cases could simply mean that the
calling convention follows C rules, but that symbolic name generation
follows C++ rules.  But then this would probably make it impossible
to call an extern "C" static member function from C code, which
kind of makes the 'extern "C"' specifier confusing at best.

-- David R. Tribble, david@tribble.com --


[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/14
Raw View
David R Tribble <david@tribble.com> wrote:

> Indeed.  Otherwise, you'd have to add verbiage to the standard to
> address the ambiguities that will arise in code such as:
>
>     class Foo
>     {
>     public:
>         extern "C" static void  func();
>     };
>
>     class Bar
>     {
>     public:
>         extern "C" static void  func();
>     };

This is only a problem if you func() has C language linkage name, not
C language linkage type. These are separate in the ISO standard.

> In many implementations, 'extern "C"' implies that name mangling does
> not occur.  If both Foo::func() and Bar::func() are translated into
> object symbols without name mangling, they could very well (and most
> likely will on most real implementations) have the same symbolic name.
> Finding good working in the standard to address such a possibility
> might be difficult.

No change to the standard would be necessary other than the one I've
proposed. The name would still have C++ language linkage. That's what
the standard already says, and I haven't suggested a change to that.

I have suggested a change to the rules about whether static member
functions can have C language linkage type.

You may want to reread the rules about this in section 7.5 of the
standard to see what already exists, and what's new in my proposal.

> OTOH, the name mangling rule need not apply for static members;
> an extern "C" linkage in these cases could simply mean that the
> calling convention follows C rules, but that symbolic name generation
> follows C++ rules.  But then this would probably make it impossible
> to call an extern "C" static member function from C code, which
> kind of makes the 'extern "C"' specifier confusing at best.

Functions of C language linkage type can already be declared with C++
language linkage name. Here's an example:

    // define extern "C" function type
    extern "C" typedef int c_func();

    // declare function so it gets C language linkage type
    c_func name_gets_mangled;

    // define function; it gets C++ language linkage name
    int name_gets_mangled()
    {
        return 12;
    }

The above example demonstrates something already in the standard, not
something new I'm proposing. The function name, "name_gets_mangled"
will still be mangled in this case, but the function has C language
linkage type.

As you say, these functions can't be called from C code.

    -- Darin


[ 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: clamage@eng.sun.com (Steve Clamage)
Date: 1999/09/14
Raw View
David R Tribble <david@tribble.com> writes:


> ... you'd have to add verbiage to the standard to
>address the ambiguities that will arise in code such as:

>    class Foo
>    {
>    public:
>        extern "C" static void  func();
>    };

>    class Bar
>    {
>    public:
>        extern "C" static void  func();
>    };

>In many implementations, 'extern "C"' implies that name mangling does
>not occur.  If both Foo::func() and Bar::func() are translated into
>object symbols without name mangling, they could very well (and most
>likely will on most real implementations) have the same symbolic name.
>Finding good working in the standard to address such a possibility
>might be difficult.

The standard does not say anything at all about name mangling.  It
merely defines the cases when two names do and do not refer to the
same entity.

If the above syntax were allowed and no other change were to be
made to the standard, I think it is clear that the two functions
are distinct. The implementation would have to ensure that the
two function definitions did not collide. Name mangling is an
obvious solution for implementations that mangle names.

There's an implicit assumption running through this thread that
if I write
 extern "C" int foo();
in a C++ program, "foo" refers to the same function that in C
would be declared
 int foo();

I don't believe the standard requires that to be the case.  It says
the details are implementation-defined.  If the static member
functions wound up with mangled names, the implementation could
just document the mangling scheme.

--
Steve Clamage, stephen.clamage@sun.com


[ 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: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/09/11
Raw View
Darin Adler wrote:

> Here's a concrete example:
>
>     extern "C" typedef void c_linkage_func();
>
>     c_linkage_func non_member_func();
>
>     class C {
>       static c_linkage_func static_member_func();
>     };

I think that you mean

   c_linkage_func non_member_func;

here.

In any cases, what about friend functions ?

--

Valentin Bonnard


[ 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: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/12
Raw View
In article <7rbiei$tm1@enews3.newsguy.com>, Darin Adler
<darin@bentspoon.com> writes
>That's not true. The scope information you refer to is part of the function
>name, not its type. Note that the *names* of all member functions will still
>have C++ linkage even if my proposal is adopted.

The problem is a very long standing one.  Basically we need to go back
to CFront that was a translator from C++ to C.  All the extern "C" meant
was that the item so qualified did not need translating.  IOWs it was
concerned purely with linkage (and that was about names).  Later on with
the growth of native C++ compilers there was the problem that calling
conventions also mattered (and there are real world implementations
where the C and C++ calling conventions are different even though the
compilers come from the same implementor).  This introduced a problem
with pointers to function.  The late change in the standard was aimed at
providing a fix for that problem.

Now if your compiler has identical calling conventions for C and C++
functions you have no problem with using a pointer to static member
function for callback.  You have no need for the extern "C"
qualification.  If the calling conventions are different then you need
to persuade the compiler writer to provide something such as extern "C
call" which fixes the calling conventions without touching the name-
mangling.

I suspect that in the case you quote (Metrowerks CodeWarrior) there is
no problem because the calling conventions for C and C++ functions are
identical.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/12
Raw View
Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:

> In any cases, what about friend functions ?

The current standard wording allows friend functions to have C language
linkage name and C language linkage type. There's no problem there.

    -- Darin
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/12
Raw View
Me:
> Here's a concrete example:
>
>     extern "C" typedef void c_linkage_func();
>
>     c_linkage_func non_member_func();
>
>     class C {
>       static c_linkage_func static_member_func();
>     };

As Valentin pointed out, the correct example is:

    extern "C" typedef void c_linkage_func();

    c_linkage_func non_member_func;

    class C {
        static c_linkage_func static_member_func;
    };

I included some extra "()" by accident in the original.

wmm@fastdial.net:
> However, I'm very much afraid that at this point it's not sufficiently broken
> to be fixable under defect report procedures, and by the five-year review time
> it will have become a mostly moot point, as most code will have been updated
> to reflect the requirements in the Standard.

A thought on this point: I don't know of a single compiler that correctly
implements this rule yet that also distinguishes C and C++ function pointers
as required by the standard. So I don't think it's likely that most code
will be updated by the five-year review. The only code that would be broken
by this change would be code that:

    1) tried to use C language linkage type for a static member function
(with an extern "C" or the typedef technique)
    2) due to the rule, instead got C++ language linkage type for the static
member function
    3) used the static member function in a way that will work with C++
language linkage type only, such as passing a function pointer

I don't think that will be particularly common.

In fact, I wasn't aware of the typedef technique (using an extern "C"
function type to declare a function with C language linkage type and C++
language linkage name) until a few weeks ago when it was suggested to a
large group of programmers on another list.

The discussion on that list never touched on the point that C language
linkage type for static member functions was non-standard. I discovered that
fact myself when I subsequently decided to explore the standard to find out
if the typedef technique was required to work.

    -- Darin
---
[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/12
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
> The problem is a very long standing one.  Basically we need to go back
> to CFront that was a translator from C++ to C.  All the extern "C" meant
> was that the item so qualified did not need translating.  IOWs it was
> concerned purely with linkage (and that was about names).

I'm familiar with that. I was using CFront in 1988 to develop the System 7
version of the Macintosh Finder. I used and understood extern "C" as it
existed them.

> Later on with the growth of native C++ compilers there was the problem that
> calling conventions also mattered (and there are real world implementations
> where the C and C++ calling conventions are different even though the
> compilers come from the same implementor).  This introduced a problem with
> pointers to function.  The late change in the standard was aimed at providing
> a fix for that problem.

I understand this as well. Thanks for clarifying it.

> Now if your compiler has identical calling conventions for C and C++
> functions you have no problem with using a pointer to static member
> function for callback. You have no need for the extern "C" qualification.

Unfortunately, this is not true.

The standard requires that extern "C" function pointers have distinct type
from non-extern-"C" function pointers regardless of whether the calling
conventions for the two languages happen to be identical. Read paragraph
7.5/1, where it says "Two function types with different language linkages
are distinct types even if they are otherwise identical." There's no
condition on that sentence. The types are distinct in all conforming
compilers.

> If the calling conventions are different then you need to persuade the
> compiler writer to provide something such as extern "C call" which fixes the
> calling conventions without touching the name- mangling.

I don't need a new feature for this. Declaring a function with C language
linkage type does it. It's part of the standard language and doesn't require
an extension. It just can't be used with static member functions, which was
the point of my defect report.

    -- Darin


[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/09
Raw View
[ moderator's note: forwarded to C++ committee for handling. -sdc ]

Section 7.5 [dcl.link] says, in paragraph 4, "A C language linkage is
ignored for the names of class members and the member function types of
class member functions." This makes good sense, since C linkage names
typically aren't compatible with the naming used for member functions at
link time, nor is C language linkage function type necessarily compatible
with the calling convention for passing "this" to a non-static member
function.

But C language linkage type (not name) for a static member function is
invaluable for a common programming idiom. When calling a C function that
takes a pointer to a function, it's common to use a private static member
function as a "trampoline" which retrieves an object reference (perhaps by
casting) and then calls a non-static private member function. If a static
member function can't have a type with C language linkage, then a global or
friend function must be used instead. These alternatives expose more of a
class's implementation than a static member function; either the friend
function itself is visible at namespace scope alongside the class definition
or the private member function must be made public so it can be called by a
non-friend function.

I have experience with this idiom because it comes up when using the
Macintosh toolbox from C++. One of the compilers I use does not yet enforce
the difference between function pointers with C and C++ linkage, and the
other allows C language linkage for static member functions. If either
compiler was updated to fully comply with the standard as it's currently
written, I'd have to expose parts of the interfaces of classes for the
reasons stated above.

Suggested Resolution: Change the sentence in paragraph 4 of 7.5 [dcl.link]
to: "A C language linkage is ignored for the names of class members and the
member function types of non-static class member functions." The example
need not be changed because it doesn't involve a static member function.

    -- Darin


[ 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: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/10
Raw View
In article <7r95ff$2bt0@enews3.newsguy.com>, Darin Adler
<darin@bentspoon.com> writes
>Suggested Resolution: Change the sentence in paragraph 4 of 7.5 [dcl.link]
>to: "A C language linkage is ignored for the names of class members and the
>member function types of non-static class member functions." The example
>need not be changed because it doesn't involve a static member function.
>
The problem with this is that along with calling conventions we have
scope information (class name or namespace) that gets stripped off by
extern "C".  I seem to recall that when we were considering the issue of
whether linkage was part of the function type (very late in the
Standardisation process, though Josee Lajoie and I had been promoting it
for several years) we came to the conclusion that all that could be done
was a further level of indirection in which an extern "C" global
function forwarded to the class static function.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ 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: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/11
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:

> The problem with this is that along with calling conventions we have
> scope information (class name or namespace) that gets stripped off by
> extern "C".

That's not true. The scope information you refer to is part of the function
name, not its type. Note that the *names* of all member functions will still
have C++ linkage even if my proposal is adopted.

My proposal is to allow the *types* of static member functions have C
linkage, while still requiring *names* that have C++ linkage. That's exactly
what one of my compilers does already (Metrowerks CodeWarrior Pro 5), and it
works great.

The standard already makes the distinction between the name and type and
allows functions with names that have C++ linkage and types that have C
linkage. The function named "f2" in the example on page 124 (7.5/4) is one
of these.

Here's a concrete example:

    extern "C" typedef void c_linkage_func();

    c_linkage_func non_member_func();

    class C {
      static c_linkage_func static_member_func();
    };

In this case, the standard says that non_member_func will have C++ linkage
for its name and C linkage for its type, but static_member_func will have
C++ language linkage for its name and for its type. I'd like
static_member_func to have C linkage for its type.

Please consider my proposal in that light and don't dismiss it just because
the names of member functions can't have C linkage.

    -- Darin
---
[ 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: wmm@fastdial.net
Date: 1999/09/11
Raw View
In a previous article,  Francis Glassborow  <francis@robinton.demon.co.uk>
writes:
>
>In article <7r95ff$2bt0@enews3.newsguy.com>, Darin Adler
><darin@bentspoon.com> writes
>>Suggested Resolution: Change the sentence in paragraph 4 of 7.5 [dcl.link]
>>to: "A C language linkage is ignored for the names of class members and the
>>member function types of non-static class member functions." The example
>>need not be changed because it doesn't involve a static member function.
>>
>The problem with this is that along with calling conventions we have
>scope information (class name or namespace) that gets stripped off by
>extern "C".

This is covered by the "ignored for the names of class members" -- the
extern "C" would have no effect on the scope information (mangling or
whatever).

>I seem to recall that when we were considering the issue of
>whether linkage was part of the function type (very late in the
>Standardisation process, though Josee Lajoie and I had been promoting it
>for several years) we came to the conclusion that all that could be done
>was a further level of indirection in which an extern "C" global
>function forwarded to the class static function.

I never understood the reason this idea was rejected (I raised it during
those deliberations, based on popular X and Motif bindings that used
static member functions as callbacks).  However, I'm very much afraid
that at this point it's not sufficiently broken to be fixable under defect
report procedures, and by the five-year review time it will have become a
mostly moot point, as most code will have been updated to reflect the
requirements in the Standard.

     -----  Posted via NewsOne.Net: Free Usenet News via the Web  -----
     -----  http://newsone.net/ --  Discussions on every subject. -----
   NewsOne.Net prohibits users from posting spam.  If this or other posts
made through NewsOne.Net violate posting guidelines, email abuse@newsone.net
---
[ 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              ]