unnamed namespace and friend method

Discussion in 'C++' started by John Ratliff, Feb 6, 2008.

  1. John Ratliff

    John Ratliff Guest

    Can you declare a friend method if the method is defined in the unnamed
    namespace?

    This is basically what I'd like to do:

    namespace {
    MyClass *ptr;

    void fnc(unsigned long my_ul, short *my_s_ptr) {
    // blah blah whatever
    ptr->callme();
    }
    }

    class MyClass {
    friend void fnc(unsigned long, short *);

    private:
    void callme();
    }

    g++ doesn't like this, but all is well if I put things in the global
    namespace.

    I suppose I could create a fake namespace, but before I do, can I do
    what I want somehow? I also tried
    friend void ::fnc(unsigned long, short *);
    but that's no good either.

    Thanks,

    --John Ratliff
     
    John Ratliff, Feb 6, 2008
    #1
    1. Advertising

  2. * John Ratliff:
    > Can you declare a friend method if the method is defined in the unnamed
    > namespace?
    >
    > This is basically what I'd like to do:
    >
    > namespace {
    > MyClass *ptr;
    >
    > void fnc(unsigned long my_ul, short *my_s_ptr) {
    > // blah blah whatever
    > ptr->callme();
    > }
    > }
    >
    > class MyClass {
    > friend void fnc(unsigned long, short *);
    >
    > private:
    > void callme();
    > }
    >
    > g++ doesn't like this, but all is well if I put things in the global
    > namespace.
    >
    > I suppose I could create a fake namespace, but before I do, can I do
    > what I want somehow? I also tried
    > friend void ::fnc(unsigned long, short *);
    > but that's no good either.


    Why not make fnc a static member function.

    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Feb 6, 2008
    #2
    1. Advertising

  3. John Ratliff

    John Ratliff Guest

    Alf P. Steinbach wrote:
    > * John Ratliff:
    >> Can you declare a friend method if the method is defined in the
    >> unnamed namespace?
    >>
    >> This is basically what I'd like to do:
    >>
    >> namespace {
    >> MyClass *ptr;
    >>
    >> void fnc(unsigned long my_ul, short *my_s_ptr) {
    >> // blah blah whatever
    >> ptr->callme();
    >> }
    >> }
    >>
    >> class MyClass {
    >> friend void fnc(unsigned long, short *);
    >>
    >> private:
    >> void callme();
    >> }
    >>
    >> g++ doesn't like this, but all is well if I put things in the global
    >> namespace.
    >>
    >> I suppose I could create a fake namespace, but before I do, can I do
    >> what I want somehow? I also tried
    >> friend void ::fnc(unsigned long, short *);
    >> but that's no good either.

    >
    > Why not make fnc a static member function.


    Sorry. I didn't mention what I was doing.

    fnc is a callback used by a C-library. I was reading the FAQ on pointer
    to members:

    http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2

    Q: How do I pass a pointer-to-member-function to a signal handler, X
    event callback, system call that starts a thread/task, etc?

    A: Don't.

    re: static member functions

    Something about name mangling and calling conventions. I'm hoping my
    code will eventually work on Windows, Linux, and OS X even though right
    now my sole target is Linux/g++.

    --John Ratliff
     
    John Ratliff, Feb 6, 2008
    #3
  4. * John Ratliff:
    > Alf P. Steinbach wrote:
    >> * John Ratliff:
    >>> Can you declare a friend method if the method is defined in the
    >>> unnamed namespace?
    >>>
    >>> This is basically what I'd like to do:
    >>>
    >>> namespace {
    >>> MyClass *ptr;
    >>>
    >>> void fnc(unsigned long my_ul, short *my_s_ptr) {
    >>> // blah blah whatever
    >>> ptr->callme();
    >>> }
    >>> }
    >>>
    >>> class MyClass {
    >>> friend void fnc(unsigned long, short *);
    >>>
    >>> private:
    >>> void callme();
    >>> }
    >>>
    >>> g++ doesn't like this, but all is well if I put things in the global
    >>> namespace.
    >>>
    >>> I suppose I could create a fake namespace, but before I do, can I do
    >>> what I want somehow? I also tried
    >>> friend void ::fnc(unsigned long, short *);
    >>> but that's no good either.

    >>
    >> Why not make fnc a static member function.

    >
    > Sorry. I didn't mention what I was doing.
    >
    > fnc is a callback used by a C-library. I was reading the FAQ on pointer
    > to members:
    >
    > http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2
    >
    > Q: How do I pass a pointer-to-member-function to a signal handler, X
    > event callback, system call that starts a thread/task, etc?
    >
    > A: Don't.
    >
    > re: static member functions
    >
    > Something about name mangling and calling conventions. I'm hoping my
    > code will eventually work on Windows, Linux, and OS X even though right
    > now my sole target is Linux/g++.


    When you're passing function pointers you can forget about name
    mangling, it's irrelevant.

    Calling convention is a formal problem, but not a practical problem.

    Anyway, if you want to avoid that little formal hurdle, why don't you
    place the class in the anonymous namespace? Or, if the class is to be
    exposed to other modules, but with the callback function not exposed,
    consider using a namespace named MyClass_detail. Or, for example,
    consider the PIMPL idiom.

    An appropriate solution much depends on what your real issue is (as
    opposed to attempted technical solution), and what you're willing to accept.

    However, I'd go for the simple static member function, and simply say
    that any compiler that doesn't give you a C-compatible calling
    convention, if such should turn out to exist, just isn't good enough
    (and chances are that for such a hypothetical compiler, there would be
    some way to adjust the calling convention).

    Cheers, & hth.,

    - Alf


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Feb 6, 2008
    #4
  5. Andrey Tarasevich, Feb 7, 2008
    #5
  6. John Ratliff

    James Kanze Guest

    On Feb 6, 7:33 pm, "Alf P. Steinbach" <> wrote:
    > * John Ratliff:


    [...]
    > > fnc is a callback used by a C-library. I was reading the FAQ
    > > on pointer to members:


    > >http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2


    > > Q: How do I pass a pointer-to-member-function to a signal handler, X
    > > event callback, system call that starts a thread/task, etc?


    > > A: Don't.


    > > re: static member functions


    > > Something about name mangling and calling conventions. I'm
    > > hoping my code will eventually work on Windows, Linux, and
    > > OS X even though right now my sole target is Linux/g++.


    > When you're passing function pointers you can forget about
    > name mangling, it's irrelevant.


    > Calling convention is a formal problem, but not a practical
    > problem.


    The fact that an `extern "C"' function has a different type is a
    real, practical problem, since it means that trying to pass the
    address of a static member won't compile with a compliant
    compiler. Just because g++ and VC++ have a bug here doesn't
    mean that all compilers do. (I get a diagnostic from Sun CC,
    and I'm willing to bet that Comeau will give me one as well.)

    > However, I'd go for the simple static member function, and
    > simply say that any compiler that doesn't give you a
    > C-compatible calling convention, if such should turn out to
    > exist, just isn't good enough (and chances are that for such a
    > hypothetical compiler, there would be some way to adjust the
    > calling convention).


    The problem isn't calling conventions, per se (although on an
    Intel, I've actually encountered different convetions). The
    problem is that the the linkage is part of the type, and that a
    conformant compiler will enforce the type. And there are
    conformant compilers around that do enforce it.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Feb 7, 2008
    #6
  7. * James Kanze:
    > On Feb 6, 7:33 pm, "Alf P. Steinbach" <> wrote:
    >> * John Ratliff:

    >
    > [...]
    >>> fnc is a callback used by a C-library. I was reading the FAQ
    >>> on pointer to members:

    >
    >>> http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2

    >
    >>> Q: How do I pass a pointer-to-member-function to a signal handler, X
    >>> event callback, system call that starts a thread/task, etc?

    >
    >>> A: Don't.

    >
    >>> re: static member functions

    >
    >>> Something about name mangling and calling conventions. I'm
    >>> hoping my code will eventually work on Windows, Linux, and
    >>> OS X even though right now my sole target is Linux/g++.

    >
    >> When you're passing function pointers you can forget about
    >> name mangling, it's irrelevant.

    >
    >> Calling convention is a formal problem, but not a practical
    >> problem.

    >
    > The fact that an `extern "C"' function has a different type is a
    > real, practical problem, since it means that trying to pass the
    > address of a static member won't compile with a compliant
    > compiler. Just because g++ and VC++ have a bug here doesn't
    > mean that all compilers do. (I get a diagnostic from Sun CC,
    > and I'm willing to bet that Comeau will give me one as well.)


    I don't know about Sun CC, but for Comeau, yes, by default in strict mode.

    With Comeau, according to the online documentation, there is an option
    "--implicit_extern_c_type_conversion" to allow this.

    The test program I used with Comeau Online:

    extern "C" void clibfunc( int (*)() ) {}

    struct S
    {
    static int foo() { return 0; }
    };

    int main()
    {
    clibfunc( S::foo );
    }

    A workaround for Comeau, without using the compile option (since Comeau
    Online only compiles there is a marginal chance that it emits some
    information to the linker so that the linker could complain):

    typedef int (*CallbackFunc)();

    extern "C" void clibfunc( CallbackFunc ) {}



    >> However, I'd go for the simple static member function, and
    >> simply say that any compiler that doesn't give you a
    >> C-compatible calling convention, if such should turn out to
    >> exist, just isn't good enough (and chances are that for such a
    >> hypothetical compiler, there would be some way to adjust the
    >> calling convention).

    >
    > The problem isn't calling conventions, per se (although on an
    > Intel, I've actually encountered different convetions). The
    > problem is that the the linkage is part of the type, and that a
    > conformant compiler will enforce the type. And there are
    > conformant compilers around that do enforce it.


    Hopefully it can also be turned off with Sun CC, e.g. as above.

    Otherwise no way, as far as I can see, to avoid making a C callback
    function extern linkage and global, visible throughout project...

    The whole thing about calling conventions etc. is an unaddressed problem
    in C++. The "extern C" syntax was probably meant to deal with it, but
    doesn't, hence the large number of non-portable language extensions and
    compiler options to deal with it. As I wrote, I think if a compiler
    doesn't support such things, then it just isn't good enough. :)


    Cheers,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Feb 7, 2008
    #7
  8. John Ratliff

    John Ratliff Guest

    > When you're passing function pointers you can forget about name
    > mangling, it's irrelevant.
    >
    > Calling convention is a formal problem, but not a practical problem.
    >
    > Anyway, if you want to avoid that little formal hurdle, why don't you
    > place the class in the anonymous namespace? Or, if the class is to be
    > exposed to other modules, but with the callback function not exposed,
    > consider using a namespace named MyClass_detail. Or, for example,
    > consider the PIMPL idiom.
    >
    > An appropriate solution much depends on what your real issue is (as
    > opposed to attempted technical solution), and what you're willing to
    > accept.
    >
    > However, I'd go for the simple static member function, and simply say
    > that any compiler that doesn't give you a C-compatible calling
    > convention, if such should turn out to exist, just isn't good enough
    > (and chances are that for such a hypothetical compiler, there would be
    > some way to adjust the calling convention).


    This has been very helpful, thank you.

    I think I will use the static member function.

    --John Ratliff
     
    John Ratliff, Feb 8, 2008
    #8
  9. John Ratliff

    James Kanze Guest

    On Feb 7, 6:38 pm, "Alf P. Steinbach" <> wrote:
    > * James Kanze:


    [...]
    > >> Calling convention is a formal problem, but not a practical
    > >> problem.


    > > The fact that an `extern "C"' function has a different type is a
    > > real, practical problem, since it means that trying to pass the
    > > address of a static member won't compile with a compliant
    > > compiler. Just because g++ and VC++ have a bug here doesn't
    > > mean that all compilers do. (I get a diagnostic from Sun CC,
    > > and I'm willing to bet that Comeau will give me one as well.)


    > I don't know about Sun CC, but for Comeau, yes, by default in
    > strict mode.


    As I expected. Comeau is generally closer to the standard than
    most compilers.

    > With Comeau, according to the online documentation, there is
    > an option "--implicit_extern_c_type_conversion" to allow this.


    Comeau uses the EDG front-end, and EDG is very, very good about
    providing options to compile broken code which happened to work
    with other compilers.

    > The test program I used with Comeau Online:


    > extern "C" void clibfunc( int (*)() ) {}


    > struct S
    > {
    > static int foo() { return 0; }
    > };


    > int main()
    > {
    > clibfunc( S::foo );
    > }


    > A workaround for Comeau, without using the compile option (since Comeau
    > Online only compiles there is a marginal chance that it emits some
    > information to the linker so that the linker could complain):


    > typedef int (*CallbackFunc)();


    > extern "C" void clibfunc( CallbackFunc ) {}


    In other words, lie to the compiler. It will probably work,
    because most linkers today are really pretty dumb.

    > >> However, I'd go for the simple static member function, and
    > >> simply say that any compiler that doesn't give you a
    > >> C-compatible calling convention, if such should turn out to
    > >> exist, just isn't good enough (and chances are that for such a
    > >> hypothetical compiler, there would be some way to adjust the
    > >> calling convention).


    > > The problem isn't calling conventions, per se (although on an
    > > Intel, I've actually encountered different convetions). The
    > > problem is that the the linkage is part of the type, and that a
    > > conformant compiler will enforce the type. And there are
    > > conformant compilers around that do enforce it.


    > Hopefully it can also be turned off with Sun CC, e.g. as above.


    I rather doubt it, but I've not tried to.

    > Otherwise no way, as far as I can see, to avoid making a C
    > callback function extern linkage and global, visible
    > throughout project...


    That's about the sum of it. You can put it in anonymous
    namespace, but in practice, that doesn't mean much for an extern
    "C" function.

    > The whole thing about calling conventions etc. is an
    > unaddressed problem in C++. The "extern C" syntax was
    > probably meant to deal with it, but doesn't, hence the large
    > number of non-portable language extensions and compiler
    > options to deal with it.


    I'm not sure what you mean here. I've never used any
    non-portable language extensions with regards to linkage. And
    I've used compilers where C and C++ used different calling
    conventions.

    > As I wrote, I think if a compiler doesn't support such things,
    > then it just isn't good enough. :)


    For numerous reasons, compilers will continue to support broken
    code. Even with Sun CC, it is just a warning (for now---the
    message definitly indicates that it will become an error at some
    time in the future). Still, there are definite reasons why
    the standards committee added the linkage to the type. (I don't
    think it was originally part of Stroustrup's intent, although
    you'd have to ask him to be sure.)

    Presumably, since it is part of the standard, other compilers
    will add such checks in the future.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Feb 8, 2008
    #9
  10. * James Kanze:
    > On Feb 7, 6:38 pm, "Alf P. Steinbach" <> wrote:
    >
    >> The whole thing about calling conventions etc. is an
    >> unaddressed problem in C++. The "extern C" syntax was
    >> probably meant to deal with it, but doesn't, hence the large
    >> number of non-portable language extensions and compiler
    >> options to deal with it.

    >
    > I'm not sure what you mean here. I've never used any
    > non-portable language extensions with regards to linkage.


    Hm. OK, lets agree on terminology first, that "linkage", for the
    purpose of this discussion, includes not only external, internal and
    none, but also what the standard calls "language linkage". Which is not
    very well defined, but presumably is meant to include such things as
    data representation, calling convention and name mangling (these last
    two are mentioned by the standard), which in turn determines whether
    type information is communicated across translation units.

    Now let's say you're using some abstract binary interface (ABI) that
    imposes a particular data representation, calling convention and name
    mangling. This is very common. In Windows programming the most common
    such ABI is named COM (Common Object Model or whatever current acronym).

    The 'extern "C"' syntax only standardizes strings for general C and C++
    language linkage. This is useless when there is more than one possible
    combination of calling convention and name mangling for each language,
    and it lumps together things that shouldn't be. So the compiler must
    use non-standard strings and a non-standard naming scheme (hopefully not
    a specific name for each combination!) if it is to use this syntax.

    In practice, Windows compilers let the name mangling scheme be
    determined by the language name (C or C++) and the calling convention,
    and use de-facto standard language extensions for the calling convention.

    If the 'extern' syntax had standardized a little more variation than
    just C versus C++, in particular the three most common calling
    conventions for free functions (or better, stack versus register
    passing, and for stack, right-left versus left-right plus who cleans up,
    for a total of five), and placed less emphasis on being a means to
    specify language and more emphasis on being a means to specify calling
    convention and name mangling, this mess could have been avoided.


    > And
    > I've used compilers where C and C++ used different calling
    > conventions.


    I presume you don't mean the situation when compiling the C++ code with
    switches to use calling convention 1, and the C code with the same
    compiler with switches to use calling convention 2, or with some
    unrelated C compiler?

    Do you mind clarifying which compiler(s) this was?


    >> As I wrote, I think if a compiler doesn't support such things,
    >> then it just isn't good enough. :)

    >
    > For numerous reasons, compilers will continue to support broken
    > code.


    No, on the contrary. The code is Right (TM), expressing what one needs.
    The language, offering no formally correct way to do what's right and
    needed and established practice (to have an 'extern "C"' type compatible
    function that is not in the global namespace), is Broken (TM). :)


    > Even with Sun CC, it is just a warning (for now---the
    > message definitly indicates that it will become an error at some
    > time in the future). Still, there are definite reasons why
    > the standards committee added the linkage to the type. (I don't
    > think it was originally part of Stroustrup's intent, although
    > you'd have to ask him to be sure.)
    >
    > Presumably, since it is part of the standard, other compilers
    > will add such checks in the future.


    Let's hope they make the warning very optional...


    Cheers,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Feb 8, 2008
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Razmig K
    Replies:
    3
    Views:
    689
    John L Fjellstad
    Sep 5, 2003
  2. marco_segurini
    Replies:
    4
    Views:
    1,009
    Rob Williscroft
    Jun 16, 2004
  3. marco_segurini

    unnamed namespace and friend

    marco_segurini, Feb 3, 2005, in forum: C++
    Replies:
    1
    Views:
    356
    msalters
    Feb 3, 2005
  4. Ivan Mascovich

    friend and unnamed namespace

    Ivan Mascovich, Mar 2, 2006, in forum: C++
    Replies:
    9
    Views:
    522
    Victor Bazarov
    Mar 3, 2006
  5. Johannes Schaub (litb)

    Experiment with unnamed namespace and template

    Johannes Schaub (litb), Oct 13, 2010, in forum: C++
    Replies:
    4
    Views:
    507
    Victor Bazarov
    Oct 13, 2010
Loading...

Share This Page