From: nmm1 on
In article <ed3hh7-q9s.ln1(a)cvinex--nospam--x.freeserve.co.uk>,
Chris Vine <chris(a)cvine--nospam--.freeserve.co.uk> wrote:
>
>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.

Eh? I don't see any problem for function definitions with internal
linkage - ones in different translation units are for different
functions. End of story. How the compiler fixes that up is the
compiler's business, but there are many methods, including lots
that are not based around name-mangling.


Regards,
Nick Maclaren.

--
[ 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
On 21 Jul., 15:05, Chris Vine <ch...(a)cvine--nospam--.freeserve.co.uk>
wrote:
> On Tue, 20 Jul 2010 18:49:03 CSTDaniel Kr�gler <daniel.krueg...(a)googlemail.com> wrote:
>

[snip]

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

If I correctly understand your intention, the external
linkage is not needed for the actual program functionality,
and a static extern "C" function should also work, right?

If so, what about the following approach:

(A)

// my_class.h:
extern "C" {
static void my_callback(void* data);
}

class MyClass {
protected:
void do_it();
friend void my_callback(void* data);
};

// my_class.cpp:

#include "my_class.h"

extern "C" {
static void my_callback(void* data) {
static_cast<MyClass*>(data)->do_it();
}
}

extern "C" typedef void (*CFu)(void*);

void slot(void* data, CFu f) { f(data); }

This approach combines the C-linkage of the
*type* of my_callback (not the linkage of
the name) with an internal name linkage. This
has the advantage that you can just wrap
my_callback in a namespace, if wanted, e.g.

namespace internal {
extern "C" {
static void my_callback(void* data);
}
}

This approach (with or without extra namespace)
requires a concrete declaration before the friend-
declaration, because otherwise the assumed name-
linkage would be external (see 11.4/4 in FCD).

You could even get rid of all the extern "C" stuff
in the header by a simple friend class approach.
Consider:

(B)

// my_class.h:

class MyClass {
protected:
void do_it();
friend class Caller;
};

// my_class.cpp:

#include "my_class.h"

struct Caller {
static void callback(void* data) {
static_cast<MyClass*>(data)->do_it();
}
};

extern "C" {
static void my_callback(void* data) {
Caller::callback(data);
}
}

extern "C" typedef void (*CFu)(void*);

void slot(void* data, CFu f) { f(data); }

Since the static member function is implicitly
inline, there should be do overhead involved.

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 James on
In article <c59b7f44-af05-45ca-a4b2-
822f5dfee0fd(a)y11g2000yqm.googlegroups.com>, Daniel Kr�gler wrote:
> 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.

No, that should not happen.

It is normally quite OK to define objects with the same name and signature in an anonymous namespace in different compilation units, and the anonymous namespace mechanism ensures that these refer to *different* objects whose names cannot be confused.
(What actually happens under the covers in implementations with which I am familiar is that the names are mangled in some way that is unique to the compilation unit.)

> In case of extern "C" functions this cannot happen, because all
> of these functions will refer to the same entity.

With extern "C" the names cannot be mangled, so the ODR *is* violated.
--
Cheers,
Daniel.

Mods: Note that my sending address is invalid to discourage spammers.
I can be reached using djusenet at sonadata in the dot co dot uk tld.


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

From: Seungbeom Kim on
On 2010-07-21 18:00, Daniel James wrote:
> In article <c59b7f44-af05-45ca-a4b2-
> 822f5dfee0fd(a)y11g2000yqm.googlegroups.com>, Daniel Kr�gler wrote:
>> 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.
>
> No, that should not happen.
>
> It is normally quite OK to define objects with the same name and signature in an anonymous namespace in different compilation units, and the anonymous namespace mechanism ensures that these refer to *different* objects whose names cannot be confused.
> (What actually happens under the covers in implementations with which I am familiar is that the names are mangled in some way that is unique to the compilation unit.)

A violation of the ODR with regard to unnamed namespaces can appear
in the following pattern:

// header.h
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED

namespace
{
void f() { /* ... */ }
}

inline void g() { f(); }

#endif

Now, include that header in several translation units, and the body of
g() contains calls to different functions in different translation units
-- that is a ODR violation.

--
Seungbeom Kim

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

From: Ulrich Eckhardt on
Daniel James wrote:
> In article <c59b7f44-af05-45ca-a4b2-
> 822f5dfee0fd(a)y11g2000yqm.googlegroups.com>, Daniel Krügler wrote:
>> 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.
>
> No, that should not happen.
>
> It is normally quite OK to define objects with the same name and
> signature in an anonymous namespace in different compilation units,
> and the anonymous namespace mechanism ensures that these refer to
> *different* objects whose names cannot be confused.

No, the problem is a different one. Consider this:

namespace {
void foo() { ... }
}
struct X {
friend void foo();
void bar() {
foo();
}
};

Every time this is part of a TU, the "foo" is a different one, so the
"X::bar" function refers to a different "foo", too, which violates
the ODR.

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! ]