Say I have the following class declared in a header file, with a friend function swap:
// header.h
class myClass
{
friend void swap(myClass &, myClass &);
public:
myClass(int ii = 0) : i(ii) {}
private:
int i;
};
Now I want to define swap. If I define it later in the same header file like this,
inline void swap(myClass &a, myClass &b)
{
using std::swap;
swap(a.i, b.i);
}
everything is fine. But if I remove the inline specifier, I get an error.
Now say I want to define swap in a separate implementation file instead. If I define it like this,
// impl.cc
#include "header.h"
void swap(myClass &a, myClass &b)
{
using std::swap;
swap(a.i, b.i);
}
everything is fine. But now if I add the inline specifier, I get an error.
Why does one version need inline but the other version can't have it?
From the C++ Standard (9.1.6 The inline specifier)
6 If an inline function or variable is odr-used in a translation unit,
a definition of it shall be reachable from the end of that translation
unit, and it shall have exactly the same definition in every such
translation unit (6.2). [Note: A call to the inline function or a use
of the inline variable may be encountered before its definition
appears in the translation unit. —end note] If a definition of a
function or variable is reachable at the point of its first
declaration as inline, the program is ill-formed. If a function or
variable with external or module linkage is declared inline in one
translation unit, there shall be a reachable inline declaration in all
translation units in which it is declared; no diagnostic is required.
An inline function or variable with external or module linkage shall
have the same address in all translation units. [Note: A static local
variable in an inline function with external or module linkage always
refers to the same object. A type defined within the body of an inline
function with external or module linkage is the same type in every
translation unit. —end note]
So either you declare the friend function as an inline function in a header such a way that its definition is reachable in each translation unit where it is used. Or the function is a non-inline function and its definition shall be placed in one compilation unit to satisfy the One Definition Rule.
Related
Consider the following header and assume it is used in several TUs:
static int x = 0;
struct A {
A() {
++x;
printf("%d\n", x);
}
};
As this question explains, this is an ODR violation and, therefore, UB.
Now, there is no ODR violation if our inline function refers to a non-volatile const object and we do not odr-use it within that function (plus the other provisions), so this still works fine in a header:
constexpr int x = 1;
struct A {
A() {
printf("%d\n", x);
}
};
But if we do happen to odr-use it, we are back at square one with UB:
constexpr int x = 1;
struct A {
A() {
printf("%p\n", &x);
}
};
Thus, given we have now inline variables, should not the guideline be to mark all namespace-scoped variables as inline in headers to avoid all problems?
constexpr inline int x = 1;
struct A {
A() {
printf("%p\n", &x);
}
};
This also seems easier to teach, because we can simply say "inline-everything in headers" (i.e. both function and variable definitions), as well as "never static in headers".
Is this reasoning correct? If yes, are there any disadvantages whatsoever of always marking const and constexpr variables in headers as inline?
As you have pointed out, examples one and third does indeed violate ODR as per [basic.def.odr]/12.2.1
[..] in each definition of D, corresponding names, looked up according to [basic.lookup], shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution and after matching of partial template specialization, except that a name can refer to
a non-volatile const object with internal or no linkage if the object
is not odr-used in any definition of D, [..]
Is this reasoning correct?
Yes, inline variables with external linkage are guaranteed to refer to the same entity even when they are odr-used as long all the definitions are the same:
[dcl.inline]/6
An inline function or variable shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case ([basic.def.odr]). [..] An inline function or variable with external linkage shall have the same address in all translation units.
The last example is OK because it meets and don't violate the bold part of the above.
are there any disadvantages whatsoever of always marking const and constexpr variables in headers as inline?
I can't think of any, because if we keep the promise of having the exact same definition of an inline variable with external linkage through TU's, the compiler is free to pick any of them to refer to the variable, this will be the same, technically, as having just one TU and have a global variable declared in the header with appropriate header guards
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.
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.
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.
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.