How does linker deal with virtual functions defined in multiple headers? - c++

Suppose I have
Base.h
class Base
{
virtual void foo() {...}
};
Derived1.h
class Derived1 : public Base
{
virtual void foo() {...}
};
Derived2.h
class Derived2 : public Base
{
virtual void foo() {...}
};
Header Derived1.h is included in multiple source files and Derived1 class is also used through Base interface. Since foo is virtual and is used polymorphic it can not be inlined. So it will be compiled in multiple obj files. How does linker then resolve this situation?

Member functions defined within class definition are implicitly inline(C++03 7.1.2.3).
Whether the function body actually gets inlined at point of calling is immaterial. But inline allows you to have multiple definitions of a function as long as all the definitions are same(which is disallowed by One definition rule)(C++03 7.1.2.2). The standard mandates that the linker should be able to link to (one or)many of these definitions.(C++03 7.1.2.4).
How does the linker do this?
The standard provisions for this by:
It mandates that the function definition should be present in each translation unit. All the linker has to do is link to the definition found in that translation unit.
It mandates that all definitions of this function should be exactly same, this removes any ambiguity of linking to a particular definition, if different definitions were to exist.
C++03 7.1.2 Function specifiers:
Para 2:
A function declaration (8.3.5, 9.3, 11.4) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.
Para 3:
A function defined within a class definition is an inline function. The inline specifier shall not appear on a block scope function declaration
Para 4:
An inline function shall be defined in every translation unit in which it is used and shall have exactly the same definition in every case (3.2).

Related

Inline functions in multiple translation units

Let's start with the following set of C++ files:
// my_class.h
struct MyClass
{
void my_func();
};
void MyClass::my_func()
{}
// f.h
void f1();
void f2();
// f1.cpp
#include "my_class.h"
void f1()
{
MyClass a;
a.my_func();
}
// f2.cpp
#include "my_class.h"
void f2()
{
MyClass a;
a.my_func();
}
// main.cpp
#include "f.h"
int main()
{
f1();
f2();
return 0;
}
I tried to compile this code with
$ g++ f1.cpp f2.cpp main.cpp
Obviously, the linker complained of duplicate symbol my_func:
duplicate symbol __ZN7MyClass7my_funcEv in:
/var/folders/yj/zz96q16j6vd1dq1_r3mz8hzh0000gn/T/f1-962ae7.o
/var/folders/yj/zz96q16j6vd1dq1_r3mz8hzh0000gn/T/f2-aef78c.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The next attempt I had was to move the function definition inside the class definition, so we get:
struct MyClass
{
void my_func()
{}
};
Running the same g++ command, the program compiles successfully. This is because functions defined in class definition are implicitly marked inline (§10.1.6 * 3).
The standard states:
A function declaration (11.3.5, 12.2.1, 14.3) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions specified in this section shall still be respected
Which seems somewhat in contradiction to what is written on cppreference.com:
Because the meaning of the keyword inline for functions came to mean "multiple definitions are permitted" rather than "inlining is preferred", [...]
So as far as I understand, having a function defined in the class definition makes it implicitly inline which does not necessarily mean that the compiler will choose to inline its body but will a definition of it in every translation unit. Is this correct?
The second question comes regarding template classes. Separating the declaration/definition of a template class is a problem, as described here so we can only have function definitions in the class definition which makes it implicitly inline, again, right? What is the impact of this?
Since we only have the choice of defining functions in class definitions when the class is a template, what is to be done about classes that are not template? Should we define function in source files and only keep the declaration in headers when possible?
So as far as I understand, having a function defined in the class definition makes it implicitly inline which does not necessarily mean that the compiler will choose to inline its body but will a definition of it in every translation unit. Is this correct?
Correct. When defined inside the class it is marked as inline and it is okay that that defenition is brought into multiple translation units. The compiler will handle that for you.
The second question comes regarding template classes. Separating the declaration/definition of a template class is a problem, as described here so we can only have function definitions in the class definition which makes it implicitly inline, again, right? What is the impact of this?
This is not correct. Templates are special. They aren't actually anything that will exist once the code is compiled. What a template is, is a recipe for stamping out a class or function. As such, they are implicitly inline as well to allow the template to be included in every translation unit that uses it so the compiler can stamp out a concrete class/function from it as needed. This means you can define class member functions outside of the class.
Since we only have the choice of defining functions in class definitions when the class is a template, what is to be done about classes that are not template? Should we define function in source files and only keep the declaration in headers when possible?
Typically you want to put your definitions in a cpp file. The benefit you get from this is you only need to recompile that one cpp file if you change the implementation of the functions. If they were in the header file then you need to recompile every cpp file that includes that header file which leads to longer build times.

c++ emitting inline functions

Let's say that I have a library which contains a public definition of function void foo();. The library calls this function internally. To get the best performance I want internal calls to be inlined. I also want to prevent external code from seeing the definition so that later I can change the implementation without breaking the ABI. Here is a piece of code:
MyLib.h:
void foo();
MyLibInlined.h:
inline void foo() { code here }
MyLib.cpp
#define inline
#include "MyLibInlined.h"
The question is does it break the ODR or is it considered bad practice?
EDIT:
What if foo was a member function?
The question is does it break the ODR or is it considered bad practice?
It doesn't break the ODR, but it breaks the rules in [dcl.fct.spec]:
If a function with external linkage is
declared inline in one translation unit, it shall be declared inline in all translation units in which it appears;
no diagnostic is required.
Instead you should have a public version of the function, which is not declared inline, and have an internal version which you use inside your library:
// MyLibInlined.h
inline void foo_impl() { }
Then inside the library define foo as a call to the internal one:
// MyLib.cpp
#include "MyLibInlined.h"
void foo() { foo_impl(); }
Alternatively, if all the calls to foo() are in a single file you don't need to worry at all, just define it as a non-inline function, and let the compiler inline it in the file where the definition is visible:
// MyLib.h
void foo();
// MyLib.cpp
void foo() { code here }
// use foo ...
The inline keyword doesn't mean the function will be inlined, it means the definition is provided inline in headers. The compiler doesn't need that keyword to be able to inline it within the file where it's defined, because it can see the definition. You only need the inline keyword to allow the definition to appear in multiple translation units without causing a multiple definition error.
AFAIK it does break the ODR, since inline is not so much a rule as it is a guideline. The compiler is allowed to not inline functions despite them being declared so.
On the other hand compilers are also allowed to inline functions that are not declared inline, and are likely to do so for small functions in internal calls (it can do so at link-time in some cases), so just don't worry about it.
Alternatively declare the inline version in a separate namespace and use inline namespaces to resolve it at compile-time (or using or whatever)(http://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces)
It seems to be illegal based on this (C++14 3.2/6)
There can be more than one definition of a [...] inline function with
external linkage [...] in a program provided that each definition
appears in a different translation unit, and provided the definitions satisfy the following requirements. Given
such an entity named D defined in more than one translation unit, then
[...]
— each definition of D shall consist of the same sequence of tokens
Section 3.2 is the section on the one definition rule.
This might be a cleaner variation on what you're doing:
// foo_pub.h -- public interface
#define foo() foo_pub()
void foo_pub();
// foo_private.h -- internal used by library
#define foo() foo_inline()
inline foo_inline() { ... }
// foo_pub.c -- definition for public function
void
foo_pub()
{
foo_inline()
}

Inline class method in the header file

Is there any differece between the following implementations?
class Foo
{
int bar(int x) const
{ return x * 2; }
};
class Foo
{
inline int bar(int x) const
{ return x * 2; }
};
According to the C++ 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.
And
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.
When the function is marked as inline, it tells the compiler to put the code of the function to the place where the function has been called from. You can have implicit and explicit inlines - member functions of classes are inlined implicitly, so you don't need to type it and in your case there is no difference.
7.1.2 Function specifiers
3 A function defined within a class definition is an inline function.
The inline specifier shall not appear on a block scope function
declaration. 94 (The inline keyword has no effect on the linkage of a function.) If the inline specifier is used in a friend
declaration, that declaration shall be a definition or the function
shall have previously been declared inline.
So, no. There is no difference.

A virtual member function is used if it is not pure?

C++03 3.2.2 ...An object or non-overloaded function is used if its name appears in a potentially-evaluated expression. A virtual member function is used if it is not pure...
And then later in 3.2.3 we have: Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8).
An inline function shall be defined in every translation unit in which it is used.
Along the lines I am reading: a pure virtual function is not used. The ODR applies only to functions which are used. Doesn't this imply that the following would be legal? I am guessing the answer is no, it doesn't, but then I can't understand why.
//x.h
struct A
{
virtual void f() = 0;
};
//y.cpp
#include "x.h"
void A::f()
{
}
//z.cpp
#include "x.h"
#include <iostream>
void A::f()
{
std::cout << "Hello" << std::endl;
}
//main.cpp
#include "x.h"
struct B:A
{
virtual void f()
{
A::f();
}
};
int main()
{
A* p = new B;
p->f();
}
The two clauses are not mutually exclusive.
That a virtual function is used if it is not pure, does not mean that the converse holds. If a virtual function is pure it does not mean that it is necessarily not used. It may still be used "if its name appears in a potentially evaluated expression" such as in your example: A::f();.
This code violates ODR. A::f is multiply defined. Hence it has UB.
Multiple definitions across translation units are only allowed for the following as per $3.2/5
There can be more than one definition
of a class type (clause 9),
enumeration type (7.2), inline
function with external linkage
(7.1.2), class template (clause 14),
non-static function template (14.5.5),
static data member of a class template
(14.5.1.3), member function of a class
template (14.5.1.1), or template
specialization for which some template
parameters are not specified (14.7,
14.5.4) in a program provided that each definition appears in a different
translation unit, and provided the
definitions satisfy the following
requirements.
As #Charles Bailey pointed out, your A::f is in fact used even though it's pure virtual. But that's beside the main point.
It's not accurate that the One Definition Rule does not apply to functions that are not used. We have:
3.2p1 No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.
3.2p3 Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required.
Together, these requirements seem to imply that a used function must have exactly one definition, and an unused function (including a pure virtual function which is never explicitly called) may have either no definition or a single definition. In either case, multiple definitions for a non-inline function makes the program ill-formed.
At least, I'm quite certain that's the intent. But you may be on to a hole in the phrasing, since a very literal reading does not say anywhere that multiple different definitions of the same unused function in different translation units is ill-formed.
// x.cpp
void f() {}
void g() {}
// y.cpp
#include <iostream>
void f() {
std::cout << "Huh" << std::endl;
}
void h() {}
// z.cpp
void g();
void h();
int main() {
g();
h();
return 0;
}
This is related but off-topic: from the citations it seems there is a hole in the Standard alright: it should also say a pure virtual destructor is used, and, that it must be defined; at least if there exist any derived class objects which are destroyed or if a destructor of such is defined, since the derived class destructor must call the base destructor, implicitly it does so with the qualified::id syntax. The definition of such destructors is usually trivial but cannot be elided and cannot be generated.
[class.abstract]: "A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1)."
Your A::f is called by B::f, so there must be a single definition of A::f.

Isn't C++'s inline totally optional?

I have a class that had an inline member, but I later decided that I wanted to remove the implementation from the headers so I moved the members body of the functions out to a cpp file. At first I just left the inlined signature in the header file (sloppy me) and the program failed to link correctly. Then I fixed my header and it all works fine, of course.
But wasn't inline totally optional?
In code:
First:
//Class.h
class MyClass
{
void inline foo()
{}
};
Next changed to (won't link):
//Class.h
class MyClass
{
void inline foo();
};
//Class.cpp
void MyClass::foo()
{}
And then to (will work fine):
//Class.h
class MyClass
{
void foo();
};
//Class.cpp
void MyClass::foo()
{}
I thought inline was optional, and imagined I might get by with a warning for my sloppiness, but didn't expect a linking error. What's the correct/standard thing a compiler should do in this case, did I deserve my error according to the standard?
Indeed, there is this one definition rule saying that an inline function must be defined in every translation unit it is used. Gory details follow. First 3.2/3:
Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8).
An inline function shall be defined in every translation unit in which it is used.
And of course 7.1.2/4:
An inline function shall be defined in every translation unit in which it is used and shall have exactly the same definition in every case (3.2). [Note: a call to the inline function may be encountered before its definition appears in the translation unit. ] If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. An inline function with external linkage shall have the same address in all translation units. A static local variable in an extern inline function always refers to the same object. A string literal in an extern inline function is the same object in different translation units.
However, if you define your function within the class definition, it is implicitly declared as inline function. That will allow you to include the class definition containing that inline function body multiple times in your program. Since the function has external linkage, any definition of it will refer to the same function (or more gory - to the same entity).
Gory details about my claim. First 3.5/5:
In addition, a member function, static data member, class or enumeration of class scope has external linkage if the name of the class has external linkage.
Then 3.5/4:
A name having namespace scope has external linkage if it is the name of [...] a named class (clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes.
This "name for linkage purposes" is this fun thing:
typedef struct { [...] } the_name;
Since now you have multiple definitions of the same entity in your programs, another thing of the ODR happens to restrict you. 3.2/5 follows with boring stuff.
There can be more than one definition of a class type (clause 9), enumeration type (7.2), inline function with external linkage (7.1.2) [...] in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then
each definition of D shall consist of the same sequence of tokens; and
in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3) [...]
I cut off some unimportant stuff now. The above are the two important one to remember about inline functions. If you define an extern inline function multiple times, but do define it differently, or if you define it and names used within it resolve to different entities, then you are doing undefined behavior.
The rule that the function has to be defined in every TU in which it is used is easy to remember. And that it is the same is also easy to remember. But what about that name resolution thingy? Here some example. Consider a static function assert_it:
static void assert_it() { [...] }
Now, since static will give it internal linkage, when you include it into multiple translation units, then each definition will define a different entity. This means that you are not allowed to use assert_it from an extern inline function that's going to be defined multiple times in the program: Because what happens is that the inline function will refer to one entity called assert_it in one TU, but to another entity of the same name in another TU. You will find that this all is boring theory and compilers won't probably complain, but i found this example in particular shows the relation between the ODR and entities.
What follows is getting back to your particular problem again.
Following are the same things:
struct A { void f() { } };
struct A { inline void f(); }; void A::f() { } // same TU!
But this one is different, since the function is non-inline. You will violate the ODR, since you have more than one definition of f if you include the header more than once
struct A { void f(); }; void A::f() { } // evil!
Now if you put inline on the declaration of f inside the class, but then omit defining it in the header, then you violate 3.2/3 (and 7.1.2/4 which says the same thing, just more elaborating), since the function isn't defined in that translation unit!
Note that in C (C99), inline has different semantics than in C++. If you create an extern inline function, you should first read some good paper (preferably the Standard), since those are really tricky in C (basically, any used inline-definition of a function will need another, non-inline function definition in another TU. static inline functions in C are easy to handle. They behave like any other function, apart of having the usual "inline substitution" hint. static inline in both C and C++ serve only as a inline-substitution hint. Since static will already create a different entity any time it's used (because of internal linkage), inline will just add the inline-substitution hint - not more.
Whether or not the method is actually inlined is at the sole discretion of the compiler. However the presence of the inline keyword will also affect the linkage of the method.
C++ linkage is not my specialty so I'll defer to the links for a better explanation.
http://publib.boulder.ibm.com/infocenter/zos/v1r9/index.jsp?topic=/com.ibm.zos.r9.cbclx01/inline_linkage.htm
http://en.wikipedia.org/wiki/Inline_function
Alternately you can just wait for litb to provide the gory details in an hour or so ;)
Point to note: when method is declared inline, its definition MUST be together with its declaration.
Regarding harshath.jr's answer, a method need not be declared inline if its definition has the "inline" keyword, and that definition is available in the same header, i.e.:
class foo
{
void bar();
};
inline void foo::bar()
{
...
}
This is useful for conditionally inlining a method depending on whether or not the build is "debug" or "release" like so:
// Header - foo.h
class foo
{
void bar(); // Conditionally inlined.
};
#ifndef FOO_DEBUG
# include "foo.inl"
#endif
The "inline" file could look like:
// Inline Functions/Methods - foo.inl
#ifndef FOO_DEBUG
# define FOO_INLINE inline
#else
# define FOO_INLINE
#endif
FOO_INLINE void foo::bar()
{
...
}
and the implementation could like the following:
// Implementation file - foo.cpp
#ifdef FOO_DEBUG
# include "foo.inl"
#endif
...
It's not exactly pretty but it has it's uses when aggressive inline becomes a debugging headache.