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.
Related
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.
I am referring to this answer:
https://stackoverflow.com/a/4447057/930315
I ran into a similar issue as the OP of the cited question,
having a function
template<typename T>
void func(T& val);
and its specialization
template<>
void func<mytype>(mytype& val);
resulted in a duplicate symbols linker error (the methods are implemented in a '.tpp' file that is included at the end of my header).
adding inline to the specialised function resolved the issue. Why?
Well, if you want the standard quote on this, that'd be over at [temp.expl.spec]/12
An explicit specialization of a function or variable template is
inline only if it is declared with the inline specifier or defined as
deleted, and independently of whether its function or variable
template is inline. [ Example:
template<class T> void f(T) { /* ... */ }
template<class T> inline T g(T) { /* ... */ }
template<> inline void f<>(int) { /* ... */ } // OK: inline
template<> int g<>(int) { /* ... */ } // OK: not inline
— end example ]
That's why you have to do it. It's independent because I believe doing otherwise would be needlessly restrictive, as Yola demonstrated.
This will work without inline:
file1.h
template<typename T> void func(T& val);
template<> void func<mytype>(mytype& val);
file1.cpp
template<> void func<int>(int& ) {}
But if you define template specialization in header file, than you may violate ODR
According to clause 3.2:4 in the c++ standard
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.
This explains why there is a link-time error when the specialized function is not declared inline. The program will contain multiple definitions of the specialized function, one from each module including the .tpp-file and this breaks the condition from the standard. When declaring the specialized function inline it will make the function satisfy the second part of the same clause, i.e. that an inline function must be defined in each module using the function.
When the parameterized function is not specialized it is covered by clause 3.2:6:
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
This clause states that it is OK for multiple definitions of the same template function as long as at least one of the template parameters is not specified in the code. This is to allow the decision on whether the parameterized function should be instantiated in a module to be made on local information only.
I am referring to this answer:
https://stackoverflow.com/a/4447057/930315
I ran into a similar issue as the OP of the cited question,
having a function
template<typename T>
void func(T& val);
and its specialization
template<>
void func<mytype>(mytype& val);
resulted in a duplicate symbols linker error (the methods are implemented in a '.tpp' file that is included at the end of my header).
adding inline to the specialised function resolved the issue. Why?
Well, if you want the standard quote on this, that'd be over at [temp.expl.spec]/12
An explicit specialization of a function or variable template is
inline only if it is declared with the inline specifier or defined as
deleted, and independently of whether its function or variable
template is inline. [ Example:
template<class T> void f(T) { /* ... */ }
template<class T> inline T g(T) { /* ... */ }
template<> inline void f<>(int) { /* ... */ } // OK: inline
template<> int g<>(int) { /* ... */ } // OK: not inline
— end example ]
That's why you have to do it. It's independent because I believe doing otherwise would be needlessly restrictive, as Yola demonstrated.
This will work without inline:
file1.h
template<typename T> void func(T& val);
template<> void func<mytype>(mytype& val);
file1.cpp
template<> void func<int>(int& ) {}
But if you define template specialization in header file, than you may violate ODR
According to clause 3.2:4 in the c++ standard
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.
This explains why there is a link-time error when the specialized function is not declared inline. The program will contain multiple definitions of the specialized function, one from each module including the .tpp-file and this breaks the condition from the standard. When declaring the specialized function inline it will make the function satisfy the second part of the same clause, i.e. that an inline function must be defined in each module using the function.
When the parameterized function is not specialized it is covered by clause 3.2:6:
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
This clause states that it is OK for multiple definitions of the same template function as long as at least one of the template parameters is not specified in the code. This is to allow the decision on whether the parameterized function should be instantiated in a module to be made on local information only.
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.
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.