C++ call inline function from another cpp file - c++

I'm trying to understand a few basics about extern, static, etc. and tried the following example, but I don't get why I can't call the function "just" because it's (possibly) inlined.
My first file : F1.cpp
#include <iostream>
void Modify();
int i;
int main() {
i = 1;
std::cout << "i = " << i << std::endl;
Modify();
std::cout << "i = " << i << std::endl;
return 0;
}
The second file : F2.cpp
#include <iostream>
extern int i;
inline void Modify() {
i = 99;
std::cout << "i = " << i << std::endl;
}
With inline keyword in F2.cpp, I get : undefined reference to Modify() in my F1.cpp file. Removing it, the code compiles and works fine.
I assume that the inline keyword in C++ has some sort of behaviour like the static keyword ?
I had a look at this topic aswell, but apart from the fact that the documentation says that an inline function should always be in the header file, I don't get it : C++ inline member function in .cpp file
Thanks for your help !

I assume that the inline keyword in C++ has some sort of behaviour like the static keyword ?
Similar, but different. The name still has external linkage, and the program behaves as if there's only one definition (for example, the function has the same address everywhere, and only one instance of any static variables). The effects of inline are:
The function can be defined in more than one translation unit, as long as all the definitions are identical. Regular functions can only be defined once.
The function must be defined in any translation unit that uses it. This allows the compiler to omit a non-inline definition if it doesn't need one.
Your code breaks the second rule, which might or might not lead to a link error. This is why inline functions usually need to be in headers, if you need to use them in more than one unit.

According to the C++ Standard (7.1.2 Function specifiers)
4....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.
and
4 An inline function shall be defined in every translation unit in
which it is odr-used and shall have exactly the same definition in
every case
In C ( section 6.7.4 Function specifiers of the C Standard ) function specifier inline for external functions has different semantic
7....An inline definition does not provide an external definition for the function, and does not forbid an external definition in another
translation unit. An inline definition provides an alternative to an
external definition, which a translator may use to implement any call
to the function in the same translation unit. It is unspecified
whether a call to the function uses the inline definition or the
external definition

Yes, inline has a meaning that's fairly similar to static. The specific requirement from the standard (§[basic.def.odr]/3) is:
An inline function shall be defined in every translation unit in which it is odr-used.
In this case, you've defined the inline function in one translation unit, but only declared it in the other, so you're not meeting the requirement above that it be defined in the TU where it's used.
An inline function can still have external linkage. When you do this, the standard guarantees that it results in a single function that will have the same address throughout the program.
Just in case it wasn't clear: a translation unit is basically a source file, after preprocessing, so it includes everything directly in that source file plus everything in the headers it includes, minus anything skipped over due to things like #ifdef, #if, etc.

When you declare a function inline, only the translation unit that it is defined in (in this case, F2.cpp) has access to this function. If you instead put it in a header file (say F.h), and #include "F.h" in both F1.cpp and F2.cpp, then the inline function is defined twice, once in each translation unit. Normally, this would cause a linker error, but since you declared the function inline, the linker doesn't know about your Modify() function.

Related

Meaning of multiple definitions for inline or constexpr function

This is my knowledge about function declaration and definition. If there is anything wrong, please correct me.
// Function Declaration
// This is usually put in .h header file
int occur (const char* sentence, const char& achar);
// Function Definition
// This is usually put in .cpp
int occur (const char* sentence, const char& achar) { // do job and return }
I am reading the "C++ Primer 5th Edition". Under "inline and constexpr functions # Chapter 6.5.2 P.240", it says
Unlike other functions, inline and constexpr functions may be defined
multiple times in the program.
I come up with something like this in my head:
// function delcaration .h file
constexpr int returnfour();
// function definition in .cpp file
constexpr int returnfour () { return 4; }
constexpr int returnfour () { return 4; }
Is it correct to have multiple definitions like this? What does defined multiple times in the program mean and when does someone want to do it?
Unlike other functions, inline and constexpr functions may be defined multiple times in the program.
Say you have a.h:
inline int foo() { return 10; }
constexpr int bar() { return 20; }
Now, you #include the file in couple of .cpp files.
file1.cpp:
#include "a.h"
// ... other functions
file2.cpp:
#include "a.h"
// ... other functions
int main() { return 0; }
When you compile those files, the functions foo and bar are defined in the object code of file1.cpp as well as the object code of file2.cpp. When you link those object code to create an executable, there are two definitions each of foo and bar. This is legal.
However, you are not allowed to have multiple definitions of the same inline function or constexpr function in the same compilation unit.
Using:
inline int foo() { return 10; }
inline int foo() { return 10; }
or
constexpr int bar() { return 20; }
constexpr int bar() { return 20; }
in a single cpp file is not legal.
A function declaration provides information to the compiler about the function's name, the number and type of arguments it accepts, and its return value. The compiler uses this information to check statements that attempt to call the function.
A function definition is a specific type of declaration that also includes a compound statement that implements the function (the part between the { and } of the function body).
The statement about inline and constexpr functions having more than one definition does not mean that the definition can be repeated multiple times in a single compilation unit. C++ has a separate compilation model, so the compiler does not have visibility of function definitions in one compilation unit when compiling another. However, multiple compilation units can each define an inline or constexpr function (e.g. by each #includeing the same header). The results - for the program as a whole - are undefined if different compilation units have non-equivalent definitions of the same function. A result of this is that the code for constexpr and inline functions may be duplicated within the program (e.g. inlined in multiple places, not inlined but implemented locally within an object file in a manner that is not visible to other compilation units, etc) and it is up to the compiler (usually working with other parts of the build chain) to ensure this happens in a consistent manner across compilation units.
As mentioned above inline and constexpr functions can be defined multiple times. But they should be only defined only once in each compilation units. By extension if you define them in the header and include the header in multiple compilation units they can be only defined once in the header file. NOTE: They should also have the same signature otherwise the behavior is undefined.
Both inline functions and constexpr functions are resolved at compile time and that is the reason it is possible to have multiple definitions across compilation units as long as you don't violate the ODR(one definition rule) within the compilation unit.
Please see the relevant excerpts from the C++ standard document:
7.1.5 The constexpr specifier
constexpr functions and constexpr constructors are implicitly
inline functions (7.1.2).
3.2 One-definition rule
Every program shall contain exactly one definition of every non-inline function or variable that is odr-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 odr-used.

What means "obey ODR" in case of inline and constexpr function?

I just read that constexpr and inline functions obey one-definition rule, but they definition must be identical. So I try it:
inline void foo() {
return;
}
inline void foo() {
return;
}
int main() {
foo();
};
error: redefinition of 'void foo()',
and
constexpr int foo() {
return 1;
}
constexpr int foo() {
return 1;
}
int main() {
constexpr x = foo();
};
error: redefinition of 'constexpr int foo()'
So what exactly means that, constexpr and inline function can obey ODR?
I just read that constexpr and inline functions obey one-definition rule, but they definition must be identical.
This is in reference to inline functions in different translations units. In your example they are both in the same translation unit.
This is covered in the draft C++ standard 3.2 One definition rule [basic.def.odr] which says:
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.6), 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.5) 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
and includes the following bullet:
each definition of D shall consist of the same sequence of tokens; and
You are defining functions repeatedly in one translation unit. This is always forbidden:
No translation unit shall contain more than one definition of any variable, function, class type, enumeration
type, or template. (C++11 3.2/1)
For inline functions, you are allowed to define same function in exactly the same way in more than one translation unit (read: .cpp file). In fact, you must define it in every translation unit (which is usually done by defining it in a header file):
An inline function shall be defined in every translation unit in which it is odr-used. (C++11 3.2/3)
For "normal" (non-inline, non-constexpr, non-template, etc.) functions with external linkage (non-static) functions, this will usually (no diagnostic required) lead to a linker error.
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used
in that program; no diagnostic required. (C++11 3.2/3)
To sum up:
Never define anything multiple times in one translation unit (which is a .cpp file and all directly or indirectly included headers).
You may put a certain number of things into header files, where they will be included once in several different translation units, for example:
inline functions
class types and templates
static data members of a class template.
If you have:
file1.cpp:
inline void foo() { std::cout << "Came to foo in file1.cpp" << std::endl; }
and
file2.cpp:
inline void foo() { std::cout << "Came to foo in file2.cpp" << std::endl; }
and you link those files together in an executable, you are violating the one-definition-rule since the two versions of the inline function are not same.

inline function and class and header file

Will any function defined in the header file automatically be inline?
If I declare a function in a class and give the definition outside using keyword inline, will this function be inline? If it is, why this does not against the law that inline function should be given the body at declaration?
Any function defined inside a class definition is inline. Any function marked inline is also inline.
class C {
int f() { return 3; } // inline
int g();
int h();
}
inline int C::g() { return 4; } // inline
int C::h() { return 5; } // not inline
If all this code is in a header and that header is used in more than one translation unit you'll get a complaint that C::h has more than one definition. C::f and C::g are okay because they're inline. That's the primary role of inline these days: to permit defining the same function in multiple places (provided the definitions are "the same").
is it that any function defined in the header file will automatically be inline?
No, you should make any function defined outside of class body inline by hands. Otherwise, most likely you would get ODR violation (if include header in several translation units).
ISO C++11
3.2 One definition rule
1: No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.
[...]
4: Every program shall contain exactly one definition of every non-inline function or variable that is odr-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 odr-used.
if I declare a function in a class and give the definition outside using keyword inline, will this function be inline? If it is, why this does not against the law that inline function should be given the body at declaration?
There are several ways to do member function inline:
First, according to 7.1.2/3:
A function defined within a class definition is an inline function. The inline specifier shall not appear on a block scope function declaration.90 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.
struct First
{
void first(){}
};
Second, Third and Fourth, according to 9.3/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 ]
struct STF
{
void second();
inline void third();
inline void fourth();
};
inline void STF::second(){}
void STF::third(){}
inline void STF::fourth(){}
inline is a "hint", insofar as the compiler doesn't have to honor it. It can make things inline that you don't mark inline and doesn't have to inline things that you mark as inline.
By that, I mean you shouldn't rely on it. Many recommend that you don't even use it as it is misleading. Most modern compilers completely ignore it.
The only practical use is to allow you to put static implementations into a header. Whether or not that is a good thing to do is arguable.

Why does inlining template specializations help and should I do it?

The problem with template specializations is that they're treated like normal functions because there is no template parameter used anywhere anymore.
Therefor if the following code is put in a header file it works at first.
template <typename foo>
void f(foo p)
{
std::cout << "f one" << std::endl;
}
template <>
void f<int>(int p)
{
std::cout << "f two" << std::endl;
}
But this stops working if the header is included in two files.
In this case the error I get (with VS2010) is:
templateordering.obj : error LNK2005: "void __cdecl f<int>(int)" (??$f#H##YAXH#Z) already defined in othertu.obj
And this is fixable by using the inline keyword as mentioned in many other questions.
template <>
inline void f<int>(int p)
{
std::cout << "f two" << std::endl;
}
Now this raises two questions for me:
Is there any other way to do this? Putting the specialized function in the source file doesn't seem to work. Probably because I would need some sort of declaration in the header.
What does inline actually do? It seems to be a common rule of thumb all over the internet that inline shouldn't be used because the compiler "will probably inline the function the way he likes in any case". So if the compiler may not inline a function that I declare as "inline", why does this work?
Is there any other way to do this? Putting the specialized function in the source file doesn't seem to work. Probably because I would need some sort of declaration in the header.
You need to declare the specialisation in the header, just like any other function. It's up to you whether to define it inline in the header, or in (exactly one) source file; again, just like any other function. As you say, it must be declared inline if you do define it in the header.
What does inline actually do?
Normally, the one-definition rule requires functions to be defined in exactly one translation unit in the program. In practice this means that you can't define a function in a header, since a header is intended to be included in more than one translation unit.
However, sometimes you want, or need, to define functions in headers - for example, some compilers are only able to inline a function call if they can see the definition. The inline keyword relaxes the rule, so that you can define the function in multiple translation units, as long as all the definitions are identical.
inline enables some changes to the one definition rule. Specifically, a function (including an explicit specialization of a function template) declared inline can be defined in multiple translation units (provided the definitions in different translation units are the same) and must be defined in any translation unit where it is odr-used. This is the same version of the odr rule as applies to function templates (unspecialized).
You either have to define your specialization in one translation unit (and declare it before you use it in other translation units), or you can leave the definition in the header file but make it inline.
A declaration of your specialization would look like this:
template<> void f<int>(int p);
If you use the functions with the same type from two or more files, then the functions will be defined in each file. It's just the same as having a non-template function definition in a header file that is included in multiple source files.
Marking a function as inline hints to the compiler that it can "inline" the function, i.e. put the body of the function directly in place of where the function was called. This means that the function isn't actually defined. The compiler can also decide to not inline the function, in which case the inline keyword behaves like the static keyword.
Is there any other way to do this?
Putting the specialized function in the source file doesn't seem to work. Probably because I
would need some sort of declaration in the header.
Yes, if you separate the declaration and the definition of f<int>, that is supposed to solve the linker error.
The syntax of the declaration in .h file:
template <>
void f<int>(int p);
Is there any other way to do this?
template <>
static void f<int>(int p)
{
std::cout << "f two" << std::endl;
}
or have them inline, but use special compiler flags (where available) to suppress actual inlining
What does inline actually do?
Best answer(s) are already available :)

Is it an undefined behavior to have different definitions of an inline function?

Minimal code:
// --------inline.h--------
struct X {
static inline void foo ();
};
#ifdef YES
inline void X::foo () { cout << "YES\n"; }
#else
inline void X::foo () { cout << "NO\n"; }
#endif
// --------file1.cpp--------
#define YES // <----
#include"inline.h"
void fun1 ()
{
X::foo();
}
// --------file2.cpp--------
#include"inline.h"
void fun2 ()
{
X::foo();
}
If we call fun1() and fun2(), then they will print YES and NO respectively, which means they are referring different function bodies of same X::foo().
Irrespective of this should be coded or not, my question is:
Is this a well defined or undefined behavior ?
Yes it is Undefined Behavior.
Reference:
C++03 Standard:
7.1.2 Function specifiers [dcl.fct.spec]
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). [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.
Note: 3.2 refers to the One Definition Rule, Which states:
3.2 One definition rule [basic.def.odr]
Para 1:
No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.
Undefined. You are violating ODR.
If we call fun1() and fun2(), then they will print YES and NO respectively, which means they are referring different function bodies of same X::foo().
Did you try it? With different optimization levels?
I get YES and NO, YES and YES, or NO and NO depending on the optimization level and the order in which the compiled objects are presented to the linker.
Needless to say, this is undefined behavior.