Nonmember friend function is always inline - c++

I am very new to C++, and when I am trying to learn the friend function, I saw from friend description on Cppreference that:
2) (only allowed in non-local class definitions) Defines a non-member function, and makes it a friend of this class at the same time. Such non-member function is always inline.
class X {
int a;
friend void friend_set(X& p, int i) {
p.a = i; // this is a non-member function
}
public:
void member_set(int i) {
a = i; // this is a member function
}
};
Does this mean that all friend functions always have to be inline? In another word, must the friend functions be defined completely inside the class?
However, I also found an instance where the friend function is defined outside the class from Cplusplus
// friend functions
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
Rectangle() {}
Rectangle (int x, int y) : width(x), height(y) {}
int area() {return width * height;}
friend Rectangle duplicate (const Rectangle&);
};
Rectangle duplicate (const Rectangle& param)
{
Rectangle res;
res.width = param.width*2;
res.height = param.height*2;
return res;
}
I am really confused by this conflict. Is my understanding of inline wrong?
What does it mean by "a nonmember friend function defined inside the class is automatically inline"?

any function defined inside a class (member or non-member friend) is always implicitly inline. That's because class definitions are generally in header files, and you don't want any non-inline function definitions in a header file (having a non-inline function in a header leads to multiple definitions if the header is #included in more than one source file).
If you want a function to be non-inline, you need to define it outside of a class definition. If its a member or friend you still need to declare it inside the class, since members and friends must be declared in the class. You just don't want it defined in the class.
This all gets into the difference between a definition and a declaration in C++ -- they are two distinct things, though every definition is also implicitly a declaration, not every declaration is a definition. As a result, when the spec says 'declaration' it often means 'declaration that is not also a definition'

Related

Declare, then define a class method - Why an error?

Why doesn't this compile?
class Test
{
void foo();
void foo()
{ }
};
But these will compile:
void bar();
void bar()
{ }
// In same header/file
class Test
{
void foo();
};
void Test::foo()
{ }
The compiler would say that given method cannot be overloaded. The method Test::foo is not being overloaded - it is the same function with exact same signature.
It's explicitly prohibited by the C++ standard. Right there at [class.mfct/1]
A member function may be defined in its class definition, in which
case it is an inline member function, or it may be defined outside of
its class definition if it has already been declared but not defined
in its class definition. A member function definition that appears
outside of the class definition shall appear in a namespace scope
enclosing the class definition. Except for member function definitions
that appear outside of a class definition, and except for explicit
specializations of member functions of class templates and member
function templates ([temp.spec]) appearing outside of the class
definition, a member function shall not be redeclared.
It is just the way it is in C++. Redeclaring a class member is not allowed (unless you consider an out-of-class definition as another declaration). Redeclaring a namespace member is OK as long as you obey ODR.
Why doesn't this compile?
class Test {
void foo();
void foo() { }; // wrong
};
Because, as StoryTeller and others answered, you are declaring and defining the same member function void Test::foo(void) twice (and the inside-class definition of foo is implicitly inline).
If you want to define a member function in your header file after the class, you'll better declare it explicitly as inline like this:
class Test {
inline void foo();
};
and later define that member function (e.g. below in the same header file):
void Test::foo() {
// body of Test::foo
}
BTW, if you declare a member function with outside definition like above, and that member function is not inline but is defined in some header file which is included in several translation units, that function would be multiply defined and the linker would complain.
void foo();
and
void foo() {}
are two ways of declaring functions in a class definition. The first only declares the function and the second declares the function and also implements it. Therefore the compiler assumes that you are going to re-declare the same function and is not a correct overload as the function signature is the same in both.

How are inline members of classes compiled?

I am new to c++ (and to programming itself) and this is what I heard:
If we compile an ordinary function, The compiler creates a pointer to that function and place the instructions that make up the body of the function elsewhere. This is how an ordinary function gets compiled. But in case of inline functions, the compiler generates code during compilation and replaces it with the inline function call.
My question is when member functions (of a C++ class) are compiled, are they treated as inline functions or are they treated as ordinary functions?
They are just like normal functions, with one exception: if you write the function definition inside the class definition (example below), then the function is automatically given the inline keyword:
[C++11: 9.3/2]: A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2), or it may be defined outside of its class definition if it has already been declared but not defined in its class definition.
struct T
{
void foo() // the same as `inline void foo()`
{
// ...
}
};
That doesn't automatically mean the class will be inlined, though; the inline keyword is just a hint and is largely ignored nowadays when it comes to deciding whether to actually inline a function, though it does assuredly affect linkage.
You asked:
are they treated as inline functions or are they treated as ordinary functions?
Member functions of classes can be inline or non-inline depending on how they are declared and defined.
Here's the relevant info from the standard:
9.3 Member functions
2 A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2), or it may be defined outside of its class definition if it has already been declared but not defined in its class definition. A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition...
Example:
class A
{
A() : data(0) {} // Inline function
inline A(A const& copy) : data(copy.data) {}
// Inline function. The keyword inline
// can be used but not necessary.
int data;
};
3 An inline member function (whether static or non-static) may also be defined outside of its class definition provided either its declaration in the class definition or its definition outside of the class definition declares the function as inline. [ Note: Member functions of a class in namespace scope have external linkage. Member functions of a local class (9.8) have no linkage. See 3.5. —end note ]
Example:
class A
{
A(); // Declaration doesn't say whether the function is inline or not.
inline A(A const& copy); // Declaration says the function is inline.
int data;
};
inline A::A() : data(0) {} // Implementation says the function is inline.
inline A(A const& copy) : data(copy.data) {}
4 There shall be at most one definition of a non-inline member function in a program; no diagnostic is required. There may be more than one inline member function definition in a program. See 3.2 and 7.1.2.
Example:
class A
{
A(); // Declaration doesn't say whether the function is inline or not.
inline A(A const& copy); // Declaration says the function is inline.
int data;
};
inline A(A const& copy) : data(copy.data) {}
// Must be defined in a .h file since the declaration says the function is inline.
A::A() : data(0) {} // Non-inline implementation.
// It must be defined in only one translation unit (a .cpp file, not a .h file).
Whether to inline a function or not is entirely up to the compiler's discretion, which means that different compilers might have different criteria for function inlining. That being said, you can prompt the compiler to inline a function with keywords such as inline, __inline, and __forceinline. Still, it does not guarantee that your function will be inlined.
However, there are cases where it's generally impossible to inline. This link from Microsoft would probably give you a good idea about function inlining.
An example of a function that cannot be inlined will be a virtual function. As virtual function calls(i.e. which virtual function definition to call) are determined on run-time, it is impossible for the compiler to figure out which exact function definition will be called at each call of the virtual function.
#include <iostream>
class Base
{
public:
virtual int VirtualFunc();
};
class Derived1 : public Base
{
public:
virtual int VirtualFunc() { return 1; }
};
class Derived2 : public Base
{
public:
virtual int VirtualFunc() { return 2; }
};
int main(void)
{
Base* pBase;
size_t choice;
std::cin >> choice; //Get user input
if(choice == 1) //If user inputs 1, create a Derived1
pBase = new Derived1;
else if(choice == 2) //If user inputs 2, create a Derived2
pBase = new Derived2;
pBase->VirtualFunc(); //At compile-time, no idea if pBase will be Derived1 or Derived2
return 0;
}
Thank you for reading.
Compilation of class methods works same as standalone functions. If you put inline keyword before it, compiler will try to insert it's code to place, where it is called, if it's possible.

friend functions of a class inside a namespace

I've two question about this code bellow:
namespace A { class window; }
void f(A::window);
namespace A
{
class window
{
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs)
{
std::cout << rhs.a << std::endl;
}
1) why do I need to qualify the member function f inside window class to be global by doing ::f(window) ?
2) why do I need to predeclare the function f(A::window) in this particular case, whereas when the class is not defined inside a namespace it's ok for the function to be declared after the function is declared a friend.
When you declare f() as a friend it's actually done in the enclosing namespace of the containing class (A in this case) if a forward declaration is not already present.
So this...
namespace A
{
class window
{
private:
friend void ::f(window);
};
}
essentially becomes this...
namespace A
{
class window;
void f(window);
class window
{
private:
friend void f(window);
};
}
Edit: Here is a snippet from the C++ standard that explicltly talks about this scenario:
Standard 7.3.1.2 / 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 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).
As for 1), your function is not in the namespace, so you must use :: to tell the compiler to search it outside the namespace.
Otherwise, it will only look for function inside the namespace (that's why they exist). Koenig lookup doesn't apply here, as window class is inside the namespace.
not too sure about 2) though, but i bet it is related to 1).
1) because function f is declared and defined outside of the current namespace. If you moved the definition of your class into the same namespace as the function whether global or otherwise you wouldn't need to.
2) you always need to declare a function before it is referenced. Your class references the function with the friend statement.

enclosing scope

what's wrong with this code?
class matrix{
private:
friend transpose(const matrix&);
friend class invert;
public: //...
};
matrix (*p)(const matrix&)=&transpose; //error: no transpose() in scope.
what does the statement means "a friend declaration does not introduce a name into enclosing scope".This problem does not occur when friend keyword is removed
The difference between the declaration of transpose() as a friend and without the friend declaration is that if you declare "friend transpose()" all you are doing is telling the compiler that a function friend with the signature shown in the friend declaration can have access to the private members of an object of type matrix. It does not declare a function transpose() with this signature - you still have to do this outside the scope of the matrix class.
If you remove the 'friend' keyword, you are declaring a member function transpose() inside the class matrix, so the compiler actually has seen a function it can take the address of.
§7.3.1.2 [namespace.memdef] p3
[...] If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup or by qualified lookup until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). [...]
See also this question of mine.
Friend functions are functions that are not members of a class but
they still have access to the private members of the class.
I should point out that a friend function declaration
may be placed in either the private section or the public section,
but it will be a public function in either case, so it is clearer to
list it in the public section.
class MyClass
{
private:
int data;
public:
MyClass(int value);
friend void myFriend(MyClass *myObject);
};
void myFriend(MyClass *myObject)
{
cout << myObject->data<< endl;
}
MyClass::MyClass(int value)
{
data = value*2;
}
int main()
{
MyClass myObject(3);
myFriend(&myObject);
}
So, you need to define the friend function after you declare it.

Is a friend function defined in-class automatically inline?

If a member function is defined inside the class, it is an inline function. E.g.
struct X
{
void mem_f() {} //mem_f is inline
};
My question is whether a nonmember friend function defined inside the class is also automatically inline.
E.g.
struct Y
{
friend void friend_f() {} //is friend_f inline?
};
A relevant quote/paragraph_no from the standard would be much welcome. Thanks.
Yes, it is. §11.4/5:
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.
Such a function is implicitly inline. 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 (3.4.1).
Since the class definition is presumably in a header file, the function will be multiply-defined, so it needs to be inline.