When I attempt compiling the following code I get a linker error: Undefined symbols for architecture x86_64: \"Foo()\", referenced from: _main in main.o
using L
Why does declaring the function
constexpr
cause a linker error?
That is because constexpr
functions are implicitly inline
. Per Paragraph 7.1.5/2 of the C++11 Standard:
A
constexpr
specifier used in the declaration of a function that is not a constructor declares that function to be aconstexpr
function. Similarly, aconstexpr
specifier used in a constructor declaration declares that constructor to be aconstexpr
constructor.constexpr
functions andconstexpr
constructors are implicitlyinline
(7.1.2).
Per Paragraph 7.1.2/4, then:
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 (3.2). [...]
It's an interesting question. As Andy Prowl, constexpr
makes
the function inline
, which means that there must be
a definition of it in every translation unit which uses it;
I would have expected an error from the compiler. (Actually, if
I read §3.2/5 correctly, a diagnostic is required if you use the
function and there is no definition.)
As to why const
has different behavior: you can't mark
a non-menber function const
. If you write const int Foo();
,
it is not the function which is const
, but the type it returns
(except that if the return type is not a class type,
cv-qualifiers are ignored, so this is really the same as int
Foo();
).
The body of a constexpr
function must be visible at every point where it's used. In your case you have to move Foo()
's code to test.hpp
.
For instance, consider this code in main.cpp
:
constexpr int Foo();
int main() {
static_assert(Foo() == 42, "Ops");
}
where Foo()
is defined in test.cpp
. How the compiler is supposed to check the static_assert
condition while processing main.cpp
if it cannot see that Foo()
does return 42
. That's impossible. The whole point of constexpr
functions is that the compiler can "call" them at compile time and for this to happen it must see the code.
Therefore, this compiles fine:
constexpr int Foo() { return 42; }
int main() {
static_assert(Foo() == 42, "Ops");
}