Member access control for friend function defined inside class in C++ - c++

I understand that the following C++ code snippet should produce an error in the definition of g, because p.t.x is private and cannot be accessed there.
class P {
class T {
int x;
friend class P;
};
T t;
friend void g(P &p);
};
void g(P &p) { p.t.x = 42; }
What puzzles me is the next snippet. It differs only in the fact that the definition of the friend function g now occurs inside class P.
class P {
class T {
int x;
friend class P;
};
T t;
friend void g(P &p) { p.t.x = 42; }
};
Clang++ (both 6.0.0-1ubuntu2 and Apple version clang-1100.0.33.8) compiles the latter with no error, whereas GNU C++ (7.5.0-3ubuntu1~18.04) produces the same error as in the former snippet.
I understand that the function g defined in the latter case is not in the same scope
as the one defined in the former (cf. a related question and an older longer discussion) and it's only visible through ADL. But I think what I'm asking here is different: should the declaration friend class P in class T extend to the body of friend function g or not?
The relevant part of the C++ standard (§11.3 or §11.9.3 in more recent drafts) states that:
7 ... A friend function defined in a class is in the (lexical) scope
of the class in which it is defined. A friend function defined outside
the class is not (6.5.1).
So I understand that Clang++ and GNU C++ interpret differently what is meant by "lexical scope" (see also this answer to the previous related question). Clang++ seems to compile g as if it were a friend of class T, probably because it's in the lexical scope of class P which is a friend of class T, whereas GNU C++ does not.
Is there a bug in one of the two compilers?
If yes, which one?
Regardless of the answers to the previous questions, isn't this something that the standard should formalise better?

This looks like CWG1699 (which is still open).
1699. Does befriending a class befriend its friends?
According to 14.3 [class.friend] paragraph 2,
Declaring a class to be a friend implies that the names of private and protected members from the class granting friendship can be accessed in the base-specifiers and member declarations of the befriended class.
A friend declaration is a member-declaration, but it is not clear how far the granting of friendship goes in a friend declaration. For example:
class c {
class n {};
friend struct s;
};
struct s {
// #1 and #2 are not relevant for this question
friend void f() { c::n(); } // #3
};
In particular, if a friend function is defined inside the class definition, as in #3, does its definition have access to the private and protected members of the befriending class? Implementations vary on this point.

For starters - disclaimer: this is my interpretation of the standard and even though I think it's the right one, one can't be sure what was really meant.
tl;dr
Yes.
IMO clang++
If you look below you will notice it is formalised pretty good.
Full answer
Having said that I think there are two relevant quotes from the standard. First is this:
11.9 Member access control
1 A member of a class can be
(1.1) - private; that is, its name can be used only by members and friends of the class in which it is declared.
and the second is:
11.9.3 Friends [class.friend]
1 A friend of a class is a function or class that is given permission to use the private and protected member names from the class.
A class specifies its friends, if any, by way of friend declarations.
Such declarations give special access rights to the friends, but they do not make the nominated friends members of the befriending class.
From these two one can deduce a few things. But the most important one is that even inline friend cannot access private members of class defined inside befriended class. Why? Because it is neither member nor friend of the nested class. And from that it seems the g++ is right here.

Related

Why is a "friend class" not verified for existence?

I used to name my test class as a friend in the class to be tested, in order to enable testing private fields. I noticed that the name of the class is not verified for existence. Is it by intention?
A friend class declaration that uses an elaborated type specifier with non-qualified name of the class is actually a declaration of that class. It introduces the class as a member of the enclosing namespace. It does not require it to be pre-declared
class C
{
friend class X; // OK, introduces '::X'
};
But if you use a qualified name in a friend class declaration, it will be subjected to a regular qualified name lookup. And it must refer to a previously declared name
class X {};
class C
{
friend ::X; // OK, refers to '::X'
friend ::Y; // Error, no '::Y' in sight
};
So, if you want your class name to be "verified for existence", use qualified names in friend declarations.
Is it by intention?
I think so. It's much like a forward declaration.
Usually the friend class needs a full declaration of the friended class, but not vice versa.
To force checking an existent (declared) type you can use
class MyClass {
friend FriendClass;
};
as mentioned in #bogdan's comment.
As a side note:
How to refactor the mostly not appropriate friend pattern, I recommend you to read my Q&A post: How can I remove refactor a «friend» dependency declaration properly?
Imagine if the friend class was required to exist. How would you structure your code? For testing you have that friend declaration in your code. When you build your shipping version you aren't going to ship the test code, so you have to remove the friend declarations and rebuild everything. Now you're shipping code that's different from the code that you tested.

Why is it possible to place friend function definitions inside of a class definition?

Is it not supposed for a friend function to be explicitly defined outside of a class ?
If so why can i declare a friend function inside a class definition just like any member function ?
What is this ?
Is it only OK with some operators such as < operator or is it applicable to all operators?
If it is applicable to all of them, Is there any disadvantage for doing this ?
Should it be avoided? If so why ?
class person
{
public:
bool operator<(int num)
{
return x < num ? true : false ;
}
bool operator<(person& p)
{
return x < p.x ? true : false ;
}
friend bool operator<(int num, person &p)
{
return p.x < num ? true : false ;
}
void setX(int num)
{
x = num;
}
private:
int x;
};
Update:
I am not asking for choosing non-member operator overloading or member operator overloading.
What i want to know is that :
Why we are permitted to move the definition of friend methods inside our class definition?.
Is it not violating any things? If it is not, Why would we have friends in first place?
We could simply define overloads as member functions ( I know the limitations of member functions ) But i am saying knowing this, Why isn't compiler complaining that I haven't defined friend function outside a class definition since it doesn't need to be inside of it (because of the class parameter it has)
So why are we allowed to define a friend function inside a class definition?
Is it not supposed for a friend function to be explicitly defined outside of a class ?
Friend functions can be defined (given a function body) inside class declarations. These functions are inline functions, and like member inline functions they behave as though they were defined immediately after all class members have been seen but before the class scope is closed (the end of the class declaration). Friend functions that are defined inside class declarations are in the scope of the enclosing class.
quote
Is it only OK with some operators such as < operator or is it applicable to all operators?
It is best to try to avoid friend functions since they are opposite to what you are trying to do using a private class scope and mainly "hide" the variables. If all your functions are friend functions then what is the use of having private variables?
Still, there are some common operators which are often declared as friend functions, those are operator<< and operator>>
Alexandru Barbarosie answer is correct. It means that we can declare a friend function, which is not a member function, within a class. This can be nice to organize the code. I think an example can help to understand it in case it isn't clear.
#include <iostream>
class A {
public:
A(int val) : val(val) {}
// The following isn't a member function, it is a friend
// function declared inside the class and it has file scope
friend void draw (A &a) {
std::cout << "val: " << a.val << "\n";
}
private:
int val;
};
int main() {
A a(5);
draw(a); // outputs "val: 5"
//A::draw(a); // Error: 'draw' is not a member of 'A'
}
If you are creating a header-only class (which makes deployment vastly easier) then defining a friend function within the class is the only way to go since definitions can only appear in a single translation unit. The normal technique of include guards doesn't work since that only handles things like recursive inclusion.
This can be a big deal if you are trying to write standards-conformant code. For example, to implement the RandomNumberEngine named requirement from the C++ normative standard, it is necessary to provide operator<<. This has to be a friend to take a std::ostream& object as its first parameter (otherwise it will look like a normal, single parameter member function operator overload). Ordinarily the friend declaration would go in the class definition and and the function definition in a separate .cpp source file. But if you want a header-only implementation, it must be defined in the class to avoid multiple definition errors.
Because an operator needs to know details of the right-hand side of the expression in which is used, if it must access private data of the type which resides on that side, it needs to be friend with that class.
If you are trying to compare an int with a person, like in your example, choices are two:
you provide an implicit conversion from person to int so that < can use it without accessing any private field.
or you declare the operator as friend of person so that it can access x in the right-hand side of the comparison.
As Jack mentioned friend functions are required in places where access to private data is needed. There is also another purpose. This is related to types of inheritance. Only derived class and its friends can convert pointer to a private base to a derived type. So you might sometimes want to make some function a friend of derived class to allow this inside function body.

Can friend class be declared conditionally in C++03?

I want to declare a friend class only if some (compile-time) condition is true. For example:
// pseudo-C++
class Foo {
if(some_compile_time_condition) {
friend class Bar;
}
};
I did not find any solution on the internet. I went through all the answers to the question Generating Structures dynamically at compile time. Many of them use the C++11 std::conditional, but I would like to know if it is possible to do this in C++03 without using the preprocessor.
This solution https://stackoverflow.com/a/11376710/252576 will not work because friendship is not inherited ( friend class with inheritance ).
Edit Just to make this more easily visible, as mentioned below in the comment: This requirement is unusual. This is part of a new research project in hardware simulation, that I am working on. The testbench is written in C++, and I want to display the variables in a waveform. I have researched various other options, and figured out that I need to use a friend class, due to practical considerations. The friend will capture the values and generate the waveform, but I would prefer to have the friend only when the waveform is required, and not all the time.
Use friend std::conditional<C, friendclass, void>::type; where C is your condition. A nonclass type friend will be ignored.
The conditional template is easily implemented in C++03. However since C++03 does not support typedef friends you need to use the following syntax there
namespace detail { class friendclass {}; }
class Foo {
friend class std::conditional<C,
friendclass, detail::friendclass>::type::friendclass;
};
Note that the detail dummy class name needs to match the name of the potential friend in this workaround.
[class.friend]/3 tells this :
A friend declaration that does not declare a function shall have one of the following forms:
friend elaborated-type-specifier ;
friend simple-type-specifier ;
friend typename-specifier ;
therefore it is not possible to conditionally declare friends of a class, without a macro.
It seems, unfortunately, not possible within the C++ compiler: ie, it seems that only the preprocessor may help here. Note: Johannes has a proposal, so there is hope!
However I would note that:
friendship does not require you to actually use it
friendship is a pure compile-time construct (like access specifiers) and does not incur any runtime penalty on any major compiler
there is no reason not to have unconditional friendship, but only use it if some conditions (static or dynamic) are met.
Note: in the future, this is something that the static_if proposal could cover.
Note: Johannes has pretty much nailed it. In '03 you cannot befriend
a typedef - but if you know you have a class, then you can refer to
it's injected class name.
Johannes' answer also has the benefit of using standard library functionality which too is always a good thing.
#define some_compile_time_condition 0
class Foo;
template <int Condition> class TestCondition {
private:
friend class Foo;
struct Type {
struct Bar;
};
};
template <> class TestCondition<1> {
public:
typedef Bar Type;
};
struct Bar
{
public:
void foo (Foo &);
};
class Foo {
private:
friend struct TestCondition< some_compile_time_condition >::Type::Bar;
int m_i;
};
void Bar::foo (Foo & foo)
{
foo.m_i = 0;
}
It's still different to the requirement in that Foo always has a
friend, but the befriended class changes based on the value of the
option.
An interesting side question is whether it is an ODR violation to have
versions of Foo both with and without some_compile_time_condition
set to 1.
I think you take 1 preprocessor and write your source code inside that.
bool flag = false;
#ifdef _MY_FRIEND_
friend class sample
flag = true;
#endif
if (flag)
{
...
...
...
}
class Foo {
#ifdef _MY_FRIEND_
friend class Bar;
#endif
}
};
Here _MY_FRIEND_ is a preprocessor and if you add that preprocessor then at compile time your class Bar will be the friend class...you can use that preprocssor any where when you want to need class Bar as a friend class.other wise compile without the preprocessor then it wont allow u to add Bar as a friend class of Foo
Please correct me if i understood the question wrong.

Friend access to protected nested class

I have the following C++ code:
class A {
protected:
struct Nested {
int x;
};
};
class B: public A {
friend class C;
};
class C {
void m1() {
B::Nested n; // or A::Nested
}
};
Compiling this snippet with g++ 4.4, it does not make a difference whether I use B::Nested or A::Nested in m1. Clang accepts B::Nested, but does not compile if I A::Nested. Is that a bug in g++ or in clang?
According to the Standard, GCC is correct and Clang is wrong. It says at 11.2/4
A member m is accessible when named in class N if
m as a member of N is protected, and the reference occurs in a member or friend of class N, or in a member or friend of a class P derived from N, where m as a member of P is private or protected
This is subject of this Clang bugreport, which prevents Clang from building Qt: http://llvm.org/bugs/show_bug.cgi?id=6840 . One Clang guy says
Actually, I intentionally haven't implemented this rule yet. It is either a
drafting error or a horrible mistake. It neuters the entire 'protected'
specifier, it makes the well-formedness of code dependent on the
existence of completely unrelated classes, it imposes high costs on the
implementation, and it's formally undecidable in the presence of templates.
In C++ friends are not-transitive. Friends of your friends are not necessarily my friends.
By making Nested protected in A, you indicate that all subclasses may use this element, but nobody else is allowed to use it. You could consider this is a kind of friend. A makes all subclasses friend regarding access to the Nested struct.
Now B makes C a friend, but this does not mean that C is also a friend of A. So C should have no access to Nested.
BUT: the behavior is changed from C++03. In C++03, a nested class is a full member of the enclosing class and so has full access rights. Friendship is still NOT transitive, but now member access is.
You may want to look at http://www.rhinocerus.net/forum/language-c-moderated/578874-friend-transitive-nested-classes.html, which explains a similar problem.

friendship scope c++

In section 11.5.1 of "The C++ Programming Language", Bjarne Stroustrup writes:
Like a member declaration, a friend declaration does not introduce a name into an enclosing scope.
For example:
class Matrix
{
friend class Xform;
friend Matrix invert (const Matrix &);
//..
};
Xform x; // error: no Xform in scope
Matrix (*p) (const Matrix &) = &invert; // error: no invert() in scope
For large programs and large classes, it is nice that a class doesn’t ‘‘quietly’’ add names to its enclosing scope. For a template class that can be instantiated in many different contexts (Chapter 13), this is very important.
However, the next section then goes on to say that the class must have been previously defined, or defined in the non-class scope immediately enclosing the class that is declaring it a friend.
My question is that because of the fact that the class needs to be previous defined or defined in the nonclass scope immediately enclosing the class that is declaring it a friend, then in the first example Xform could not be out of scope, as presumably the class would have been defined before the definition of the Matrix class. Furthermore, I can't think of a situation which, given the restriction that the friend class needs to be previously defined or defined immediately after the granter's class, that the friend class will not be in scope!
Secondly, is my interpretation of Bjarne in this section correct, in that:
For friend CLASSES only, friend class must have been previously defined in an enclosing scope, OR defined immediately after the non-class scope.
For a function, must have been previously declared in an enclosing scope, OR it can also be found by having an argument of type == 'the friendship granter's' class?
You're right that Xform would need to have been defined before Matrix if the example code was supposed to work. But it wasn't supposed to work. It was an example of bad code — code that tried to have the friend declaration introduce new names into the program, and then use those names to declare a variable and initialize a pointer.
That was the entire standalone example. It wasn't just an excerpt where you were supposed to imagine additional code before or after the given code, such as definitions for Xform and invert.
Your first paraphrase is not quite correct. The definition of the friend class does not need to immediately follow the class who granted it friendship. It needs to be defined in the immediately enclosing scope. Essentially, it should be defined in the same scope as the class it's friends with. The example after the one you cite illustrates it:
class AE { /* ... */ }; // not a friend of Y
namespace N {
class X { /* ... */ }; // Y's friend
class Y {
friend class X;
friend class Z;
friend class AE;
};
class Z { /* ... */ }; // Y's friend
}
Although Y says that AE is its friend, it's not referring to the AE class declared earlier because namespace N is the immediately enclosing scope of Y and AE isn't declared there. Instead, the friend declaration must refer to some other AE class that's going to be defined in namespace N elsewhere in the program. (However, it doesn't need to be defined anywhere at all; classes can say they are friends with things that don't exist, and the program won't care. The programmers will care, though, because they'll waste time trying to find the right AE class in the source code.)
You're also wrong on your second paraphrase. The function doesn't have to have been previously declared in an enclosing scope. It just has to be declared eventually. Consider the opening example of section 11.5, where operator* is listed as a friend of both Vector and Matrix classes before the operator has been either declared or defined.
Furthermore, for the friend function to be found, it doesn't have to have arguments equal to the class's type. Stroustrup says the function "can be found through its arguments," and then refers you to section 8.2.6 for what he means by that. That's the section on name lookup.
An example of when Matrix is in scope, XForm isn't, yet there is an XForm class defined which is the friend of Matrix:
1.h
------------------------
namespace Foo
{
class Matrix
{
friend class XForm;
};
}
1.c
------------------------
#include 1.h
// XForm not in scope
// implement Matrix
2.h
------------------------
namespace Foo
{
class XForm
{
};
}
main.c
#include 1.h
#include 2.h
int main()
{
// both XForm & Matrix in scope here
}
Is this correct?
I don't know if I understand your question, but I think Bjarne thought you need to define the class (say Xform) outside Matrix if you want to use it (imagine it is some helper class you put in a header file that you don't #include in all .cpp files that #include the file with Matrix). You needn't define it if you never mention it :)
In case of functions, the situation is similar. However, there is a difference, that it can be even defined with the friend declaration (=inside the Matrix class) and, as you say, "be found by having an argument of type == 'the friendship granter's' class" (or have argument type that is a nested class thereof), by Koenig lookup.
The idea of a friend function is when you have a private class so that normally other classes cannot access what's inside - you're making a black box, BUT you want to specifically name functions that are outside that are exceptions to that rule. I think it should be thought of as not having much to do with scope, or if anything, defining a special kind of scope.
Something defined as a friend would have to be defined elsewhere, otherwise it's not a friend - it's nothing - it doesn't exist.
Was that the question?