9

I can't seem to find the answer to this newbie question. If I have a class // Header file (.h)

Class X {
public:
  friend bool operator==(const X&, const X&);
  inline size_type rows() const;
};

etc... when I go to implement the .cpp file of X, should I include the words inline & friend in the function names in the .cpp file. ie, should I implement my file similar to the below

// CPP file (.cpp)
#include "X.h"
friend bool operator==(const X&, const X&) {
  //implementation goes here
  //return true/false
}

inline size_type rows() const {
  return r;
}

or should I not include these i.e. like below

#include "X.h"
bool operator==(const X&, const X&) { ... }

size_type rows() const { ... }
Péter Török
  • 114,404
  • 31
  • 268
  • 329
theAir
  • 91
  • 1
  • 2

3 Answers3

6

No, you shouldn't, i.e. the 2nd version is correct.

friend can only be used within a class definition (it has no meaning outside of it), and the compiler looks for the function signature to find the definition of the friend function declared within your class X.

inline is used in header files (although, I guess, technically it is possible to use it in a cpp file too, just it makes no sense there). And note that inline makes sense only if you actually define the function right there - it can have no effect if you provide the function definition separately, in a cpp file.

The point of inline is to hint the compiler that the function in question can be inlined (it is no guarantee, though - the compiler is free to decide whether it inlines that function or not). If the function is inlined, any calls to it are replaced by a copy of the function body. This is practically always done for performance benefits, to save the costs of function calls, at the expense of potentially increasing program size. Now, if we want to inline a function, we want it to be inlined all over the place, not only within a single compilation unit; this is why it makes little sense to use the inline keyword inside an implementation file.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
  • 2
    actually, there is **one** use of `inline`. A function declared `inline` may appear several times in different translations units and not cause a *duplicate* error at link-time. I do not know if this is standard behavior though. – Matthieu M. Aug 22 '11 at 13:28
  • @Matthieu: In that case, the function should be defined in some header file. The compiler may decide to go against your `inline` specification; `inline` is a hint only. When that happens you may well get multiple definitions of the same function in different translation units. The linker is required not to reject the program on the basis of the one definition rule in the case of such exact duplicates that arise from `inline`. – David Hammen Aug 22 '11 at 13:42
  • @Matthieu: The standard says, in 3.2 paragraph 3, "Every program shall contain exactly one definition of every non-inline function or object that is used in that program. ... An inline function shall be defined in every translation unit in which it is used." – David Hammen Aug 22 '11 at 13:45
  • thanks guys for all the help, for the specific project i have been given, the inline function is described as above in the .h file, however we are asked not to modify the .h file at all, but rather to implement the functions in the .cpp file. Does this mean i declare that function in my .cpp file aswell with the inline tag line, and implement the 1 line of code in the braces in the .cpp file? – theAir Aug 22 '11 at 13:46
  • @theAir, you don't need the `inline` directive in the cpp file. And as I explained above, if you don't provide the definition (implementation) of the function in the header file along with the `inline` directive, it will have no effect. So your function will behave just like a regular non-inlined function. – Péter Török Aug 22 '11 at 14:17
  • @David: Thanks for the Standard mention, I was not sure if the linker behavior was specified. (And I do know the use in optimization, I just wanted to underline what `inline` meant *semantically-wise*) – Matthieu M. Aug 22 '11 at 14:19
4

When defining friend functions you can use one of two different options:

Define the friend function inside the class definition

namespace Test {
class test {
   int priv;
   friend void foo( test const & t ) { std::cout << t.priv << std::endl; }
};
}

Define them in the enclosing namespace:

namespace Test {
class test {
   int priv;
   friend void foo( test const & t );
};
void foo( test const & t ) {
   std::cout << t.priv << std::endl;
}
}

But note that there are differences regarding lookup. In particular, the first case is more restrictive (and thus should be preferred) as only ADL (Argument Dependent --aka Koening-- Lookup) will find it, while in the second case the function will be considered whenever that namespace is considered.

That is, for the compiler to consider the first function as an overload, the argument at the place of call must be a test, while in the second case it will be considered whenever the identifier matches, and might be considered as a valid option if the argument is convertible to test.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
0

You don't want the friend prefix on the function body, just the signature in the header.

John
  • 6,433
  • 7
  • 47
  • 82