Discussion:
Question
Graziano Servizi
2014-10-07 13:57:11 UTC
Permalink
I read in the 3.4.1.9 clause of the C++11 standard:

Name lookup for a name used in the definition of a friend function
(11.3) defined inline in the class granting
friendship shall proceed as described for lookup in member function
definitions. If the friend function is
not defined in the class granting friendship, name lookup in the friend
function definition shall proceed as
described for lookup in namespace member function definitions.

Later, in the 11.3.6 clause I found:


A function can be defined in a friend declaration of a class if and only
if the class is a non-local class (9.8),
the function name is unqualified, and the function has namespace scope.
[ Example:
class M {
friend void f() { }
// definition of global f, a friend of M,
// not the definition of a member function
};
— end example ]


So, if I have well understood I could write such a short code:

# include <iostream>

class P
{
friend void friend_inline()
{std :: cout << P :: Name << ' ' << p << '\n';}
static constexpr int Name = 20;
static constexpr double p = 12.5;

};

int main()
{
P p;
// how can I call friend_inline ?
}

which indeed is compiled by 4.8.3 g++ compiler. But the question is in
the comment: I tried both the call as if friend_inline was in global
scope (the standard said "global definition") and the call through the
:: scope resolution operator such as

P :: friend_inline();

Neither worked. I also tried adding a public member to P as a "wrapper"
of friend_inline (so making it and its friendship redundant), but the
compiler claimed that friend_inline was undeclared in the class scope...

I can't understand...


Graziano Servizi
David Hagood
2014-10-12 12:54:03 UTC
Permalink
Post by Graziano Servizi
# include <iostream>
class P
{
friend void friend_inline()
{std :: cout << P :: Name << ' ' << p << '\n';}
You will need to qualify "p" as well:
{std :: cout << P::Name << ' ' << P::p << '\n';}
Post by Graziano Servizi
static constexpr int Name = 20;
static constexpr double p = 12.5;
};
int main()
{
P p;
// how can I call friend_inline ?
friend_inline();
Post by Graziano Servizi
}
It's just a function.

It's probably more clear if you split the definition of the function,
the declaration of it being a friend, and the implementation:

// Declaration: there exists a function named "friend_inline"...
void friend_inline();

// Class declaration.
class P
{
// Class P allows a non-class function "friend_inline" to access its
private variables...
friend void friend_inline();
static constexpr int Name = 20;
static constexpr double p = 12.5;

};

// Definition of the function "friend_inline"
void friend_inline()
{
std::cout << P::Name << ' ' << P::p << std::endl;
}

Each of these things - declaration, friending, and definition - are
separate things. They can be combined into one statement (as in your
example) for brevity, but they still are 3 different things.

Also: be VERY CAREFUL about using friend - it's almost always a bad
idea. You are almost always better off making one or more public member
functions, and calling them, than you are exposing every last private
member to a non-member function.

somewhat OT: I wouldn't put spaces between the class name, the colon,
and the variable name in your code; they are all one thing - the name of
the object being accessed. Also, use "std::endl" to end a sequence of
insertions to a stream, not just '\n' - std::endl has more semantic
meaning to the system, it really means "I am done with this line, do
whatever you need to do, such as flushing it to the file", vs. "\n"
which just means "insert a newline character".
Jonathan Wakely
2014-10-13 09:55:33 UTC
Permalink
somewhat OT: I wouldn't put spaces between the class name, the colon, and
the variable name in your code; they are all one thing - the name of the
object being accessed. Also, use "std::endl" to end a sequence of insertions
to a stream, not just '\n' - std::endl has more semantic meaning to the
system, it really means "I am done with this line, do whatever you need to
do, such as flushing it to the file", vs. "\n" which just means "insert a
newline character".
std::endl is defined to be a newline followed by a flush, nothing more.
Continue reading on narkive:
Loading...