From: Daniel Krügler on
On 18 Jul., 00:27, Chris Vine <ch...(a)cvine--nospam--.freeserve.co.uk>
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.
>
> To minimise intercoupling with other translation units which might look
> up the header file, I thought of putting it in anonymous namespace,

In general it is a bad idea to use unnamed namespaces
within a (shared) header file, because this can easily lead to
violations of the ODR, especially if the definition is not
(inline) within the header. In case of extern "C" functions this
cannot happen, because all of these functions will refer
to the same entity. Nevertheless I don't see any reason
to confuse readers of your code because of the unnamed
namespace.

You don't say whether the implementation is in the header
or not, so this point is not clear to me.

> 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:
>
> 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,

It works in the second example, because CB is an *inner*
namespace of the unnamed namespace and thus the qualified
access via CB::my_callback refers to this entity. Note
that ::CB::my_callback would not work either nor does
::my_callback in the first example.

The reason for the difference between the first form and
the second form is that the first form uses an unqualified
name, while the second form uses qualified name. I
use the current FCD as reference in the following. As of
[namespace.memdef]/3:

"Every name first declared in a namespace is a member
of that namespace. If a friend declaration in a nonlocal
class first declares a class or function (footnote) the friend
class or function is a member of the innermost enclosing
namespace. The name of the friend is not found by
unqualified lookup (3.4.1) or by qualified lookup (3.4.3)
until a matching declaration is provided in that
namespace scope (either before or after the class
definition granting friendship). [..] If the name in a friend
declaration is neither qualified nor a template-id and the
declaration is a function or an elaborated-type-specifier,
the lookup to determine whether the entity has been
previously declared shall not consider any scopes
outside the innermost enclosing namespace. [ 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 ]"

with footnote: "this implies that the name of the class or
function is unqualified."

The last quoted normative sentence describes that an
unqualified friend declaration checks for previous
declarations only the innermost enclosing namespace,
which is the global namespace in your original example.

The tricky point is, that names introduced in scopes by
means of a using-directive don't match with the way
unqualified friend-declarations bind to a corresponding
entity. As of [basic.lookup.unqual]/2:

"The declarations from the namespace nominated by a
using-directive become visible in a namespace
enclosing the using-directive; see 7.3.4. For the purpose
of the unqualified name lookup rules described in 3.4.1,
the declarations from the namespace nominated by the
using-directive are considered members of that
enclosing namespace."

Note that above quote from friend-declaration said:

"The name of the friend is not found by unqualified
lookup (3.4.1) or by qualified lookup (3.4.3) until a
matching declaration is provided in that namespace
scope"

but declarations introduced by using-directives don't
produce *declarations* in the hosting namespace, these
names become only *visible* in that host. This interpretation
is supported by [namespace.udir]/2 (emphasize mine):

"A using-directive specifies that the names in the
nominated namespace **can be used** in the scope
in which the using-directive appears after the using-
directive. During *unqualified name lookup* (3.4.1), the
names *appear as if they were declared* in the nearest
enclosing namespace which contains both the using-
directive and the nominated namespace.

Yes, this subtle difference to normal declarations is hard
to recognize, but it exists. Informally, for unqualified
friend declarations, names introduced by using-directives
are not considered, because they are not declarations
within the hosting namespace.

[As a side note, there exists a core issue that is involved
with friend-declarations and using-declarations, but that
one should not affect your example. See

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#138

if you are interested in this discussion]

Now the difference to the qualified approach: As above
quote from [namespace.memdef]/3 implies (see also the
last note), *qualified* friend declarations perform the usual
look-up rules. In this case the naming of CB::my_callback
finds a matching reference, even though this is not
::CB::my_callback. I think this is ruled by 3.4.3.2/7,
in particular by the normative sentence:

"However, in such namespace member declarations, the
nested-name-specifier may rely on using-directives to
implicitly provide the initial part of the nested-name-specifier."

that follows

"In a declaration for a namespace member in which the
declarator-id is a qualified-id,[..]"

and which should be relevant here.

> 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?

I would get rid of the unnamed namespace in the header.
If the function definition has to be provided in the
header, you should declare it as an inline function
which prevents violations of 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! ]

From: Francis Glassborow on
Chris Vine wrote:

>
> "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


I cannot quite put my finger on it but I feel that you are missing
something. To start with, if you want to link to a C library you must
declare a function as extern "C". This isn't just a matter of (the
absence) name-mangling in C but that the way that arguments are passed
can be different between C and C++ (indeed they certainly were different
for the IBM C and C++ compilers, I do not know if they still are)

So you require an extern "C" declaration. Now once you have that yjr
fact that the declaration is lexically in a namespace becomes irrelevant
because there will be no name mangling and the declaration will be
exported to global scope.

So despite the deprecation of static at namespace scope it is still
required in this case if you want to hide a function at file scope.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Chris Vine on
On Tue, 20 Jul 2010 18:40:37 CST
Francis Glassborow <francis.glassborow(a)btinternet.com> wrote:
> I cannot quite put my finger on it but I feel that you are missing
> something. To start with, if you want to link to a C library you must
> declare a function as extern "C". This isn't just a matter of (the
> absence) name-mangling in C but that the way that arguments are passed
> can be different between C and C++ (indeed they certainly were
> different for the IBM C and C++ compilers, I do not know if they
> still are)

I think we are pretty much on the same page. It is how I got there
which is the missing link, as to which see my longer post in response
to Daniel Kruegler. I need to pass a function pointer to an
external library which must have C linkage for the reasons you describe
(otherwise I would use a static member function), which therefore needs
to appear in the header in order to be made a friend. In my enthusiasm
to avoid namespace pollution I was trying to avoid it having global
scope by putting it in some form of unnamed or named namespace. I will
give up on that quest.

I could still make it static even though its declaration is in the
header, as it is not intended that anything will try to link with it -
it is class implementation - but whilst that works it causes any other
translation units which include the header to give a warning that there
is a static function without a definition. I think I will just have a
bit of namespace pollution instead.
[excess quoting deleted --mod]

Chris

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Chris Vine on
On Tue, 20 Jul 2010 18:49:03 CST
Daniel Krügler <daniel.kruegler(a)googlemail.com> wrote:
[snip]
> 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.

Thank you for your exhaustive analysis of the interaction between
friendship and namespaces in your earlier post, which explains the
effect I observed.

The division between declaration and definition was intended to be
entirely conventional. The declaration and associated class definition
was in a header file and the implementation was in a separate file (the
translation unit) intended for compilation. The function declaration
was only in the header file because it needs to be a friend of the
class concerned and, because it must be passed as a function pointer
having C linkage to an external library, cannot be a static member
function . Otherwise, it would be entirely "private" (ie unknown) to
the outside world and, knowing what I now know, would have been
declared with internal linkage.

Given that I am forced for friendship purposes to declare this function
in the header file, I thought, entirely wrongly, that including the
function declaration within anonymous namespace might provide some
useful name mangling which would help prevent name clashes should the
same program use the same name in a different translation unit for
different purposes, equivalent to giving it internal linkage (which it
could still have, in theory, even though it is declared in the header
file).

> 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:

It doesn't do it that way: see above.

[snip]
> > 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.

OK, thank you for the explanation. I would have hoped that that is what
the standard would say but I have to say that is not what it appeared
to me to say.

Paragraph 3.2/6 of the draft C++0x standard gives a long list of things
which may be defined more than once in any one program "provided that
each definition appears in a different translation unit", of which
functions with internal linkage are not mentioned. I can now see why
they were not mentioned: functions with the same name in different
translation units with internal linkage can (and usually would)
comprise completely different code. The cases mentioned in paragraph
3.2/6 are ones for which the implementation must be the same or
equivalent to the same.

Chris



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Michael Doubez on
On 18 juil, 00:27, Chris Vine <ch...(a)cvine--nospam--.freeserve.co.uk>
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.
[snip]

There is another technique that I use in those cases: I provide a
protected class member function that performs the operation I want on
a parameter. And I call it from within the extern "C" function by
inheriting the class and breaking encapsulation.

In your example:

// class definiton

class MyClass {
protected:
void do_it();

// executes do_it() on its parameter
static void really_do_it(MyClass& c);
};

// class implementation

void MyClass::do_it()
{}


void MyClass::really_do_it(MyClass& c)
{
c.do_it();
}

extern "C" void my_callback(void* data)
{
struct BreakMyClassEncapuslation: MyClass
{
using MyClass::really_do_it;
};
BreakMyClassEncapuslation::really_do_it(*(static_cast<MyClass*>(data));
}

Not the most intuitive but it doesn't leak too much information.

In the cases, I cannot modify MyClass, I use a reinterpret cast:

extern "C" void my_callback(void* data)
{
struct BreakMyClassEncapuslation: MyClass
{
using MyClass::do_it;
};
reinterpret_cast<BreakMyClassEncapuslation*>(
static_cast<MyClass*>(data)))->do_it();
}

But AFAIK it has formally UB.

--
Michael


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]