From: Chris Vine on 17 Jul 2010 07:27 I require a function which must have a C linkage specification (it is a callback from a C library) to be a friend of a class in order to have access to protected member functions of the class: it forms part of the class implementation. Because it has to be a friend it must be declared in the class header file providing the class definition. To minimise intercoupling with other translation units which might look up the header file, I thought of putting it in anonymous namespace, thus: // *** class definition *** namespace { extern "C" void my_callback(void* data); } class MyClass { protected: void do_it(); public: friend void my_callback(void* data); }; // *** class implementation *** namespace { void my_callback(void* data) { // data here holds a pointer to a MyClass object static_cast<MyClass*>(data)->do_it(); } } void MyClass::do_it() {} // *** end of code However, this fails to compile with gcc-4.4 and gcc-4.5 with: namespace.cpp:9: error: 'void MyClass::do_it()' is protected namespace.cpp:19: error: within this context In order to enable the friend declaration really to make the function a friend of the class, I need to wrap it in a named namespace, such as: // *** class definition *** namespace { namespace CB { extern "C" void my_callback(void* data); } } class MyClass { protected: void do_it(); public: friend void CB::my_callback(void* data); }; // *** class implementation *** namespace { void CB::my_callback(void* data) { // data here holds a pointer to a MyClass object static_cast<MyClass*>(data)->do_it(); } } void MyClass::do_it() {} // *** end of code I thought every unnamed namespace declaration had with it an implicit using directive. What is the reason why one friend declaration works and not the other, and is there a better way of doing it, such as by making the function static? As functions with C linkage do not name mangle for namespaces (look-up when linking is not affected), is placing it in anonymous namespace entirely otiose anyway? Chris -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Ulrich Eckhardt on 19 Jul 2010 23:07 Chris Vine wrote: > I require a function which must have a C linkage specification (it is a > callback from a C library) to be a friend of a class in order to have > access to protected member functions of the class: it forms part of the > class implementation. Because it has to be a friend it must be > declared in the class header file providing the class definition. Okay, so far. > To minimise intercoupling with other translation units which might look > up the header file, I thought of putting it in anonymous namespace, > thus: > > // *** class definition *** > > namespace { > extern "C" void my_callback(void* data); > } Putting this into a header file will declare this function over and over again, each time in a different anonymous namespace when you include the header file from other translation units. This is ugly, but not necessarily a problem. > class MyClass { > protected: > void do_it(); > public: > friend void my_callback(void* data); > }; > > // *** class implementation *** > > namespace { > void my_callback(void* data) { > // data here holds a pointer to a MyClass object > static_cast<MyClass*>(data)->do_it(); > } > } Actually, what this does is to declare a second, unrelated anonymous namespace and inside a function with the same name (but different linkage!) than the one declared in the first namespace. > However, this fails to compile with gcc-4.4 and gcc-4.5 with: > namespace.cpp:9: error: 'void MyClass::do_it()' is protected > namespace.cpp:19: error: within this context Different function, not a friend. > In order to enable the friend declaration really to make the function a > friend of the class, I need to wrap it in a named namespace, such as: > > // *** class definition *** > > namespace { > namespace CB { > extern "C" void my_callback(void* data); > } > } > > class MyClass { > protected: > void do_it(); > public: > friend void CB::my_callback(void* data); > }; > > // *** class implementation *** > > namespace { > void CB::my_callback(void* data) { > // data here holds a pointer to a MyClass object > static_cast<MyClass*>(data)->do_it(); > } > } I'm surprised this works and I'm not sure it is legal. What might be legal is to just define it in the implementation file while skipping the (IMHO illegal) attempt to fully qualify the name: void CB::my_callback(void* data) { ... } Maybe that is even what is actually used. Since the namespace "CB" doesn't exist in the second anonymous namespace, it probably uses normal lookup rules and looks in the surrounding namespaces where it finds the "CB" from the first anonymous namespace, which was imported via the implicit using directive. > As functions with C linkage do not name mangle for namespaces > (look-up when linking is not affected), is placing it in > anonymous namespace entirely otiose anyway? Name mangling is not the issue here, I guess the linker symbol is entirely unused and only the function's address is. What I would do is to put the function into its own name space. Two variants come to mind: 1. Using a unique prefix: extern "C" void MyClassCallbackHelper(void*); This already separates it sufficiently from other code. 2. Using a C++ namespace: namespace MyClassHelper { extern "C" void callback(); } This becomes more useful than the above variant the more of those functions you have. Uli -- Sator Laser GmbH Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Chris Vine on 20 Jul 2010 04:10 On Tue, 20 Jul 2010 08:07:48 CST Ulrich Eckhardt <eckhardt(a)satorlaser.com> wrote: > Chris Vine wrote: [snip] > > To minimise intercoupling with other translation units which might > > look up the header file, I thought of putting it in anonymous > > namespace, thus: > > > > // *** class definition *** > > > > namespace { > > extern "C" void my_callback(void* data); > > } > > Putting this into a header file will declare this function over and > over again, each time in a different anonymous namespace when you > include the header file from other translation units. This is ugly, > but not necessarily a problem. That was really the intention: that is, to avoid global namespace pollution by sharing the header file. (But on looking at it further I don't now think it is achieved satisfactorily, as I say at the end.) [snip] > >// *** class implementation *** > > > > namespace { > > void my_callback(void* data) { > > // data here holds a pointer to a MyClass object > > static_cast<MyClass*>(data)->do_it(); > > } > > } > > Actually, what this does is to declare a second, unrelated anonymous > namespace and inside a function with the same name (but different > linkage!) than the one declared in the first namespace. Are you sure? When the function definition is compiled it will always have the function declaration in its own translation unit, so at that point they will share the same unnamed namespace. Paragraph 7.3.1.1/1 of the draft C++0x standard says "all occurrences of unique in a translation unit are replaced by _the same_ identifier, and this identifier differs from all other identifiers in the entire program" (my emphasis), and I think the current standard says the same. [snip] > > In order to enable the friend declaration really to make the > > function a friend of the class, I need to wrap it in a named > > namespace, such as: > > > > // *** class definition *** > > > > namespace { > > namespace CB { > > extern "C" void my_callback(void* data); > > } > > } [snip] > > // *** class implementation *** > > > > namespace { > > void CB::my_callback(void* data) { > > // data here holds a pointer to a MyClass object > > static_cast<MyClass*>(data)->do_it(); > > } > > } > > I'm surprised this works and I'm not sure it is legal. What might be > legal is to just define it in the implementation file while skipping > the (IMHO illegal) attempt to fully qualify the name: > > void CB::my_callback(void* data) { ... } > > Maybe that is even what is actually used. Since the namespace "CB" > doesn't exist in the second anonymous namespace, it probably uses > normal lookup rules and looks in the surrounding namespaces where it > finds the "CB" from the first anonymous namespace, which was imported > via the implicit using directive. As I mention above, at the point CB::my_callback() is compiled the function definition is in the same translation unit as its definition and thus in the same unnamed namespace, so this looks legal to me. > > As functions with C linkage do not name mangle for namespaces > > (look-up when linking is not affected), is placing it in > > anonymous namespace entirely otiose anyway? > > Name mangling is not the issue here, I guess the linker symbol is > entirely unused and only the function's address is. > > What I would do is to put the function into its own name space. Two > variants come to mind: > 1. Using a unique prefix: > extern "C" void MyClassCallbackHelper(void*); > This already separates it sufficiently from other code. > 2. Using a C++ namespace: > namespace MyClassHelper { extern "C" void callback(); } > This becomes more useful than the above variant the more of those > functions you have. On thinking about it further I think option 1 is much to be preferred, because the prefix will also act as a name space against any other functions of similar name in the same program also with C linkage (which might be linked in via a library). Paragraph 7.5/6 of the draft C++0x standard says: "At most one function with a particular name can have C language linkage. Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function. Two declarations for an object with C language linkage with the same name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same object. [Note: because of the one definition rule (3.2), only one definition for a function or object with C linkage may appear in the program; that is, such a function or object must not be defined in more than one namespace scope ..." It means that notwithstanding the deprecation of the use of the static keyword in favour of unnamed namespace, internal linkage via the static keyword is the only means of isolating a function with C linkage and preventing a name clash at link time with another function with C linkage of the same name. Unnamed namespaces appear to be useless for functions with C linkage. In this regard, the one definition rule as formulated in the draft C++0x standard appears to break C compatibility (including for C++ programs linking to C libraries). It states that "Every program shall contain exactly one definition of every non-inline function or variable that is used in that program; no diagnostic required." It appears to make no exception for functions with internal linkage (as opposed to inline functions, for which it does make an exception), but presumably no sane compiler is actually going to create a name conflict between two functions wth internal linkage defined in different translation units where one or more of them are linked in from a C library. Chris -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 20 Jul 2010 09:48 On 20 Jul., 16:07, Ulrich Eckhardt <eckha...(a)satorlaser.com> wrote: > Chris Vine wrote: [..] > > In order to enable the friend declaration really to make the function a > > friend of the class, I need to wrap it in a named namespace, such as: > > > // *** class definition *** > > > namespace { > > namespace CB { > > extern "C" void my_callback(void* data); > > } > > } > > > class MyClass { > > protected: > > void do_it(); > > public: > > friend void CB::my_callback(void* data); > > }; > > > // *** class implementation *** > > > namespace { > > void CB::my_callback(void* data) { > > // data here holds a pointer to a MyClass object > > static_cast<MyClass*>(data)->do_it(); > > } > > } > > I'm surprised this works and I'm not sure it is legal. What might be legal > is to just define it in the implementation file while skipping the (IMHO > illegal) attempt to fully qualify the name: > > void CB::my_callback(void* data) { ... } > > Maybe that is even what is actually used. Since the namespace "CB" doesn't > exist in the second anonymous namespace, it probably uses normal lookup > rules and looks in the surrounding namespaces where it finds the "CB" from > the first anonymous namespace, which was imported via the implicit using > directive. Whether it works depends how the OP actually provided the implementation. As you descibed in a previous part (not repeated here), there can be problems, if the header is included in more than one translation unit. You are right, that a *qualified* friend-declaration will follow normal lookup-rules. This is (somewhat indirectly) described in [namespace.memdef]/3, especially with the recently added note in the FCD: "[ Note: the other forms of friend declarations cannot declare a new member of the innermost enclosing namespace and thus follow the usual lookup rules. �end note ]" As you describe, it is possible to define the function just as void CB::my_callback(void* data) { ... } because namespace CB can be referenced by name within the global namespace (see also [namespace.qual]/6 in C++03 or [namespace.qual]/7 in the FCD) HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 20 Jul 2010 09:49 On 20 Jul., 21:10, Chris Vine <ch...(a)cvine--nospam--.freeserve.co.uk> wrote: > On Tue, 20 Jul 2010 08:07:48 CST > > >// *** class implementation *** > > > > namespace { > > > void my_callback(void* data) { > > > // data here holds a pointer to a MyClass object > > > static_cast<MyClass*>(data)->do_it(); > > > } > > > } > > > Actually, what this does is to declare a second, unrelated anonymous > > namespace and inside a function with the same name (but different > > linkage!) than the one declared in the first namespace. > > Are you sure? When the function definition is compiled it will always > have the function declaration in its own translation unit, so at that > point they will share the same unnamed namespace. Paragraph 7.3.1.1/1 > of the draft C++0x standard says "all occurrences of unique in a > translation unit are replaced by _the same_ identifier, and this > identifier differs from all other identifiers in the entire > program" (my emphasis), and I think the current standard says the same. Its still unclear to me how you provide your *single* implementation of the extern "C" function with name my_callback. Since it is an function with external linkage there can only be one definition. Since it is an extern "C" function, all these functions "named" by different unnamed namespaces are referring to the same function. So you can only provide a *single* definition in one translation unit without violating the ODR. > > void CB::my_callback(void* data) { ... } > > > Maybe that is even what is actually used. Since the namespace "CB" > > doesn't exist in the second anonymous namespace, it probably uses > > normal lookup rules and looks in the surrounding namespaces where it > > finds the "CB" from the first anonymous namespace, which was imported > > via the implicit using directive. > > As I mention above, at the point CB::my_callback() is compiled the > function definition is in the same translation unit as its definition > and thus in the same unnamed namespace, so this looks legal to me. It would violate the ODR, if at least a second translation unit also provides a definition of my_callback. It is completely irrelevant, how different the namespace names are - the namespace protection works only on the C++ level. Consider: namespace A { extern "C" void foo() {} } namespace B { extern "C" void foo() {} } This is already ill-formed, because there are two definitions of foo() in the same translation unit. If these exist in two different translation units, you would violate the ODR in a way that causes undefined behavior, unless both separate definitions where declared as inline functions. > Unnamed namespaces appear to be useless for functions with C linkage. This is correct. > In this regard, the one definition rule as formulated in the draft > C++0x standard appears to break C compatibility (including for C++ > programs linking to C libraries). It states that "Every program shall > contain exactly one definition of every non-inline function or variable > that is used in that program; no diagnostic required." It appears to > make no exception for functions with internal linkage (as opposed to > inline functions, for which it does make an exception), but presumably > no sane compiler is actually going to create a name conflict between > two functions wth internal linkage defined in different translation > units where one or more of them are linked in from a C library. This is no break versus C. If you have multiple definitions of a function named X with internal linkage in different translation units, all these functions are independent and different entities, so they are not the same function and the fact that all of them provide a single definition is *not* a violation of the ODR. The extra-case mentioned for inline functions is necessary, because the wording gives freedom to provide *multiple* definitions of the *same* function - this is completely unique. The behaviour of compilers in regard to function definitions with internal linkage has nothing to do with saneness, it is required. There are *no* duplicate definitions! In contrast: If you would omit a single definition of such a function that is used in the program, you are violating the ODR. HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 3 4 Prev: templates and default parameters Next: UTF-8 messages in exceptions ? |