C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Imaginary friends

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
White Wolf
Guest





PostPosted: Sun Jul 31, 2005 1:15 am    Post subject: Imaginary friends Reply with quote



I have a dilemma. It all boils down to this:

// Header

struct X {
friend void f(X&);
private:
somestuff
};


// Implementation

static void friend f(X&x) {
whatever
}

Why static? Because I do not like implementation details to leak out. Yes,
the outside world will see a rogue f() in X's namespace, but calling it will
lead to linker errors. And I only call f() inside the x.cpp, but:

Is this legal? What does the standard say about it?

g++ just says that f is not friend, while Comeau:

"ComeauTest.c", line 6: error: external/internal linkage conflict with
previous
declaration
static void f(X&x) {x.i=42;}

--
WW aka Attila
:::
Never wrestle with a pig: You both get all dirty, and the pig likes it.



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

Back to top
Tokyo Tomy
Guest





PostPosted: Sun Jul 31, 2005 11:47 am    Post subject: Re: Imaginary friends Reply with quote



White Wolf wrote:
Quote:
I have a dilemma. It all boils down to this:

// Header

struct X {
friend void f(X&);
private:
somestuff
};


// Implementation

static void friend f(X&x) {
whatever
}

Why static? Because I do not like implementation details to leak out. Yes,
the outside world will see a rogue f() in X's namespace, but calling it will
lead to linker errors. And I only call f() inside the x.cpp, but:

Is this legal? What does the standard say about it?

g++ just says that f is not friend, while Comeau:

"ComeauTest.c", line 6: error: external/internal linkage conflict with
previous
declaration
static void f(X&x) {x.i=42;}

--
IMHO, the "friend" is a key word of access control. The "friend void

f(X&)" in class X declares that f is a friend to class X and is
permitted to access to the private part of class X. The f in class X is
not a member function of class X.

The "friend" in "static void friend f(X&x)" has no meaning because it
is not clear who is a friend to whom, and may be illegal.

Therefore the code below should work, ... yes with VC 7.1, but no with
g++.

The g++ reported errors:

storage class specifiers mismatch:
the line (1) was declared 'extern', and
the line (2) was declared 'static'

I thought this was reasonable, and I added 'static' to the line (1),
but g++ did not allow me to do so. I could not find out any solutions
except to delete "static" at the line (2).

[code]
// Header

struct X {
friend static void f(X&); // (1)
private:
//somestuff
int n;
};


// Implementation

static void /*friend*/ f(X&x) { // (2)
//whatever
x.n = 3; //access to private part of x
}

int main( )
{
X x, y;

f(x);
//x.f(y); // error
return 0;
}


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


Back to top
Carl Barron
Guest





PostPosted: Sun Jul 31, 2005 11:48 am    Post subject: Re: Imaginary friends Reply with quote



White Wolf <wolof (AT) freemail (DOT) hu> wrote:

Quote:
I have a dilemma. It all boils down to this:

// Header

struct X {
friend void f(X&);
private:
somestuff
};


// Implementation

static void friend f(X&x) {
whatever
}

Why static? Because I do not like implementation details to leak out. Yes,
the outside world will see a rogue f() in X's namespace, but calling it will
lead to linker errors. And I only call f() inside the x.cpp, but:

Is this legal? What does the standard say about it?

g++ just says that f is not friend, while Comeau:

"ComeauTest.c", line 6: error: external/internal linkage conflict with
previous
declaration
static void f(X&x) {x.i=42;}
class X

{
void friendly_f_impl(); // impliment f here!!
public:
friend void f(X &x) {x.friendly_f_impl();}
};

any rogue f's will create linker errors as f is an inline function
whose definition is given in the class definition, any other is an
error. violation of one defintion rule and even if the compiler does not
inline f, it should be caught by the linker.








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


Back to top
Mirek Fidler
Guest





PostPosted: Sun Jul 31, 2005 11:53 am    Post subject: Re: Imaginary friends Reply with quote

White Wolf wrote:
Quote:
I have a dilemma. It all boils down to this:

// Header

struct X {
friend void f(X&);
private:
somestuff
};


// Implementation

static void friend f(X&x) {
whatever
}

Why static? Because I do not like implementation details to leak out. Yes,

Why not

struct X {
private:
static void f(X&);
};

?

Seems like natural solution to me. Of course, perhaps it does not match
you scenario....

Mirek

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


Back to top
Richard Corden
Guest





PostPosted: Sun Jul 31, 2005 1:06 pm    Post subject: Re: Imaginary friends Reply with quote


White Wolf wrote:

[...]

Quote:
// Header

struct X {
friend void f(X&);
private:
somestuff
};


// Implementation

static void friend f(X&x) {
whatever
}


[...]

Quote:
Is this legal? What does the standard say about it?

As you've written it, to make it work you would have to add a storage
specifier to the friend declaration.

struct X {
friend /* static */ void f(X&);
};


// Implementation
static void f(X&x) {
}

But 11.4/7 says you cannot have storage class specifiers on the friend
declaration.


You can probably change the code to:

// h
struct X;
static void f(X&);

struct X
{
friend void f(X&);
};

// implementation
static void f(X&)
{
}

11.4/3 says that the friend declaration will have the same linkage as
the previous declaration so I believe this is formulation is OK.

If I can be so bold as to make a comment though, I think that without
copious commenting there is a strong danger of a future programmer
thinking that you've incorrectly made the declarations static and so
removing them.

There's also the danger that compilers actually stop supporting
namespace static declarations - however the relationship between unnamed
namespace declarations and export might un-deprecate this. ;)



Regards,

Richard



--
Richard Corden

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


Back to top
White Wolf
Guest





PostPosted: Sun Jul 31, 2005 4:39 pm    Post subject: Re: Imaginary friends Reply with quote

Carl Barron wrote:
[SNIP]
Quote:
class X
{
void friendly_f_impl(); // impliment f here!!
public:
friend void f(X &x) {x.friendly_f_impl();}

I cannot do that (my static f is a friend of another class as well, which
musn't show up in X-es interface). And my question wasn't how else I can
solve it, but it was "Is this legal? What does the standard say about it?"

--
WW aka Attila
:::
Always do right. This will gratify some people and astonish the rest. -
Mark Twain



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


Back to top
White Wolf
Guest





PostPosted: Sun Jul 31, 2005 4:40 pm    Post subject: Re: Imaginary friends Reply with quote

Mirek Fidler wrote:
[SNIP]
Quote:
Why not

struct X {
private:
static void f(X&);
};

?

Seems like natural solution to me. Of course, perhaps it does not match
you scenario....
[SNIP]


For exaclty that reason. Smile And may I stress it again? My question was:

Is this legal? What does the standard say about it?

--
WW aka Attila
:::
Sometimes a majority only means that all the fools are on the same side.



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


Back to top
White Wolf
Guest





PostPosted: Sun Jul 31, 2005 4:41 pm    Post subject: Re: Imaginary friends Reply with quote

White Wolf wrote:
[SNIP]
Quote:
static void friend f(X&x) {
[SNIP]


Damn copy-paste. That friend should not be there. It wasn't in the code I
have tested, I have no idea how did it get to my post. Sorry for that.
Sad((

--
WW aka Attila
:::
Be consistent (but not all the time)



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


Back to top
White Wolf
Guest





PostPosted: Sun Jul 31, 2005 4:41 pm    Post subject: Re: Imaginary friends Reply with quote

Tokyo Tomy wrote:
Quote:
White Wolf wrote:
I have a dilemma. It all boils down to this:

// Header

struct X {
friend void f(X&);
private:
somestuff
};


// Implementation

static void friend f(X&x) {
whatever
}
[SNIP]
IMHO, the "friend" is a key word of access control. The "friend void
f(X&)" in class X declares that f is a friend to class X and is
permitted to access to the private part of class X. The f in class X is
not a member function of class X.

The "friend" in "static void friend f(X&x)" has no meaning because it
is not clear who is a friend to whom, and may be illegal.

There was no static friend in my code.

Quote:
I thought this was reasonable, and I added 'static' to the line (1),
but g++ did not allow me to do so. I could not find out any solutions
except to delete "static" at the line (2).
[SNIP]


Which is no solution to what I have asked, since I have asked if it is legal
(not by some compiler, but by the standard) to have it static.


--
WW aka Attila
:::
Quit smoking on the anniversary of your birth, not the day of your death.
- Corky Peterson



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


Back to top
White Wolf
Guest





PostPosted: Sun Jul 31, 2005 4:45 pm    Post subject: Re: Imaginary friends Reply with quote

Richard Corden wrote:
[SNIP]
Quote:
You can probably change the code to:

// h
struct X;
static void f(X&);

struct X
{
friend void f(X&);
};

// implementation
static void f(X&)
{
}
[SNIP]


Yep, that seems to work. Except that one gets warnings (with gcc) in every
translation unit including the header, that f"(X&) is declared but not
used". That would require ifdefs ... I guess I am just better off leaving
them non-static.

--
WW aka Attila
:::
What's the difference between roast beef and pea soup? Anyone can roast
beef.



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


Back to top
Richard Corden
Guest





PostPosted: Mon Aug 01, 2005 10:26 am    Post subject: Re: Imaginary friends Reply with quote


White Wolf wrote:
Quote:
Richard Corden wrote:
[SNIP]

You can probably change the code to:

// h
struct X;
static void f(X&);

struct X
{
friend void f(X&);
};

// implementation
static void f(X&)
{
}

[SNIP]

Yep, that seems to work. Except that one gets warnings (with gcc) in every
translation unit including the header, that f"(X&) is declared but not
used". That would require ifdefs ... I guess I am just better off leaving
them non-static.

I thought of a different way that I think achieves the same goal.

struct SPECIAL_TYPE_ONLY_DEFINED_IN_X_CPP;

struct X
{
friend void f (X&, SPECIAL_TYPE_ONLY_DEFINED_IN_X_CPP const &);
};


// implementation

struct SPECIAL_TYPE_ONLY_DEFINED_IN_X_CPP {};

void f (X&, SPECIAL_TYPE_ONLY_DEFINED_IN_X_CPP const &)
{
}

void bar (X & x)
{
f (x, SPECIAL_TYPE_ONLY_DEFINED_IN_X_CPP ());
}


What I like about this approach is that the name you give the type can
help document for other developers that this function should not be used
outside of this translation unit.


Regards,

Richard




--
Richard Corden

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


Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Mon Aug 01, 2005 12:33 pm    Post subject: Re: Imaginary friends Reply with quote

Richard Corden wrote:
Quote:
White Wolf wrote:

[...]

// Header

struct X {
friend void f(X&);
private:
somestuff
};

// Implementation

static void friend f(X&x) {

[I presume that the presence of friend here is a copy/paste
error.]

Quote:
whatever
}

[...]

Is this legal? What does the standard say about it?

As you've written it, to make it work you would have to add a
storage specifier to the friend declaration.

struct X {
friend /* static */ void f(X&);
};

// Implementation
static void f(X&x) {
}

But 11.4/7 says you cannot have storage class specifiers on
the friend declaration.

You can probably change the code to:

// h
struct X;
static void f(X&);

struct X
{
friend void f(X&);
};

// implementation
static void f(X&)
{
}

11.4/3 says that the friend declaration will have the same
linkage as the previous declaration so I believe this is
formulation is OK.

I may work, but it certainly isn't legal. Function f is a
distinct entity in each translation unit in which it occurs, and
the one definition rule says that all names in a class
definition must bind to the same entity in all translation
units.

In practice, of course, it will almost certainly work. In fact,
one wonders if there wasn't some intent for it to work, at least
at one time. Otherwise, what's the point of §11.4/3: "A
function first declared in a friend declaration has external
linkage. Otherwise, the funtion retains its previous linkage."
If the class definition is to be in a header file, the only way
you can avoid a violation of the one definition rule is if all
friends have external linkage.

--
James Kanze GABI Software
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


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


Back to top
White Wolf
Guest





PostPosted: Mon Aug 01, 2005 6:02 pm    Post subject: Re: Imaginary friends Reply with quote

Richard Corden wrote:
[SNIP]
Quote:
I thought of a different way that I think achieves the same goal.

struct SPECIAL_TYPE_ONLY_DEFINED_IN_X_CPP;

struct X
{
friend void f (X&, SPECIAL_TYPE_ONLY_DEFINED_IN_X_CPP const &);
};
[SNIP]
What I like about this approach is that the name you give the type can
help document for other developers that this function should not be used
outside of this translation unit.
[SNIP]


This sounds good. But it still "contaminates" the namespace, and ADL may
find that function. I think if we could combine the above with in some way
with SFINAE, we may just even eliminate that last issue.

--
WW aka Attila
:::
I started out with nothing... I still have most of it.



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


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.