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.
Related
Sometimes I have some capture-less lambda defined at the top of a header file, which is used in the following part of the header:
//#include statements
namespace detail {
auto constexpr lambda = [](/* args */){ /* body */ };
}
// in some function or whatever, use `lambda`
Often I'm told in during code reviews that I should put not only constexpr specifier, as I do, but also the inline specifier.
Why should I do that? What are the advantages?
I've tried reading inline specifier on cppreference, but I think I lack to much terminology to understand it at the moment.
You should be using inline if the variable is defined in a header file. If it is not inline, then every translation unit that includes the header file will get that definition. That means you have multiple definitions for a single name which is an ODR (One Definition Rule) violation. Those do not require any diagnostics, so they can lead to hard to find bugs.
By making the variable inline, you fix the problem by telling the compiler/linker that it can throw out all of the duplicated definitions and just use a single one.
According to the C++ 17 Standard (10.1.5 The constexpr specifier)
1 The constexpr specifier shall be applied only to the definition of a
variable or variable template or the declaration of a function or
function template. A function or static data member declared with
the constexpr specifier is implicitly an inline function or variable
(10.1.6). If any declaration of a function or function template has
a constexpr specifier, then all its declarations shall contain the
constexpr specifier.
In the code snippet in your question the variable lambda is not a static data member.
namespace detail {
auto constexpr lambda = [](/* args */){ /* body */ };
}
So if the namespace detail has external linkage then and the variable lambda also has the external linkage. In this case if the header will be included in several compilation units then the one definition rule will be broken. To avoid such a situation you should declare the variable as an inline variable.
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 have a header file where string are defined as static global.
namespace space {
#define NAME(P) static std::string const s_##P = #P
NAME(foo); NAME(bar); //... other values
#undef NAME
}
In another header, an enum is defined and a template specialization provides the mapping between the enum and a string in space.
enum class letter { alpha, beta };
template<letter> std::string const & mapping();
#define MAPPING(P1,P2) template<> std::string const & mapping<letter::P1>() { return space::s_##P2; }
MAPPING(alpha,foo)
MAPPING(beta,bar)
#undef MAPPING
The above code doesn't link when the header is included in more than one translation unit because the specializations definitions do not match - due to global redefinition per translation unit (I guess).
Wrapping the mapping functions in anonymous namespace or adding static keyword solves the linking issue but then the compiler complains that the functions are defined but not used [-Wunused-function].
template<letter> static std::string const & mapping();
But, defining the specializations as constexpr, there is no longer any link or warning issue.
template<letter> std::string const & mapping();
#define MAPPING(P1,P2) template<> constexpr std::string const & mapping<letter::P1>() { return space::s_##P2; }
I understand why the non-static version fails at link time and why the static version works and triggers warnings. But I don't understand why the constexpr specifier solves both issues.
Can you please give an explanation and even better, a rational in the standard ?
Function template specializations are functions, and are therefore subject to the one-definition rule in the same manner as functions that are not template specializations.
The linker errors you saw when the functions were declared neither static nor constexpr were due to multiple definitions of the same function template specializations which each had external linkage.
When you added static, you made the linkage internal. This made it safe for each translation unit to contain its own copy of the definitions. However, in any TU in which those functions were not called, the compiler knew that (due to internal linkage) they could not be called from any other TU either, making them unused.
With constexpr, the functions become inline implicitly according to the standard, but their linkage is not affected. Since they are inline, you can have multiple definitions, but since they have external linkage, the compiler does not complain when one TU does not use them.
functions declared with the constexpr specifier are inline functions.
From the C++ 20 Standard (9.2.5 The constexpr and consteval specifiers)
1 The constexpr specifier shall be applied only to the definition of a
variable or variable template or the declaration of a function or
function template. The consteval specifier shall be applied only to
the declaration of a function or function template. A function or
static data member declared with the constexpr or consteval specifier
is implicitly an inline function or variable (
Why does cppreference define type_traits xxx_v shortcuts as inline constexpr and not just constexpr?
For example, see is_integral_v:
template< class T >
inline constexpr bool is_integral_v = is_integral<T>::value;
Is this just a matter of style or is there some difference in behavior? As far as I know constexpr variables are implicitly inline.
Edit: Looking at the draft of the latest standard, it also uses inline constexpr. The question actually applies to the standard, then.
[dcl.constexpr]/9
A constexpr specifier used in an object declaration declares the object as const.
[basic.link]/3.2
A name having namespace scope has internal linkage if it is the name of
-a non-inline variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage
Without inline specifier, is_integral_v would have internal linkage. This could be problematic if you compared two pointers to this same variable name taken in different translation unit.
Nota Bene: the inline specifier is redundant with constexpr only if the variable is a class static data member.
Following an exemple of easy violation of the one definition rule that could happen if is_integral_v where not inline.
bad_type_trait.h
template<class T>
constexpr auto bad_is_integral_v=std::is_integral<T>::value;
my_header.h
#include "bad_type_trait.h"
void f(const bool& x);
inline void g()
{
f(bad_is_integral_v<int>);
//g ODR use the static variable bad_is_integral_v.
//"ODR use" approximate definition is:
// the variable is refered by its memory address.
}
source1.cpp
#include "my_header.h"
void my_func1(){
g(); //the definition of g in this translation unit.
}
source2.cpp
#include "my_header.h"
void my_func2(){
g(); //is not the same as the definition of g in this translation unit.
}
In the two translation units, the variable bad_is_integral_v is instantiated as separate static variables. The inline function g() is defined in these two translation units. Inside the definition of g(), the variable bad_is_integral_v is ODR used, so the two definitions of g() are different, which is a violation of the one definition rule.
[basic.link]/3.2 applies to names of "a non-inline variable of non-volatile const-qualified type". A variable template isn't a variable, just like a class template isn't a class, a function template isn't a function, and a cookie cutter isn't a cookie. So that rule doesn't apply to the variable template is_integral_v itself.
A variable template specialization is a variable, however, so there are some questions about whether that rule gives it internal linkage. This is core issue 1713, the direction of which is that the rule is not applicable.
Core issue 1713, however, wasn't resolved in time for C++17. So LWG decided to simply plaster inline all over the variable templates just to be safe, because they don't hurt, either.
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.