Can constexpr and inline functions be re-defined?
c++, constexpr, function, inline
Solution
Yes unlike other functions, inline and constexpr functions may be defined multiple times in the program. However, the definitions must match exactly.
Justification according to the standard:
From § 7.1.5/2 The constexpr specifier [dcl.constexpr]:
`constexpr` functions and `constexpr` constructors are implicitly `inline`.
From § 3.2/6 One definition rule [basic.def.odr]:
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), `inline` function with external linkage ... in a program provided that each definition appears in a different translation unit...
From § 7.1.2/4 Function specifiers [dcl.fct.spec]:
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.
Thus, since a `constexpr` function is implicitly `inline` it has all the attributes of an `inline` function. Therefore, `constexpr` functions can have more than one definition provided that each definition appears in a different translation unit.
Why your program fails:
In your case the program fails because you are violating this rule. That is, you redefine the same `constexpr` function in the same translation unit (i.e., main.cpp).
Problem
I am verifying a statement on C++ Primer that: Unlinke other functions, inline and constexpr functions may be defined multiple times in the program. I used two definitions of a constexpr `cfunc()` below, expecting `foo_0()` will call the 1st def while `foo_1()` will call the 2nd def. However the attempt failed with compilation error (in the end). WHy? ``` constexpr int cfunc(){ return 42; } int foo_0(){ return cfunc(); } constexpr int cfunc(){ return 42; } int foo_1(){ return cfunc(); } int main(int argc, char **argv) { cout << foo_0() << endl; cout << foo_1() << endl; /* testconstexprfunc2.cpp:24:15: error: redefinition of ‘constexpr int cfunc()’ */ /* testconstexprfunc2.cpp:16:15: error: ‘constexpr int cfunc()’ previously defined here */ return 0; } ```