Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to declare constexpr class in a header and define it in a separate .cpp file?

I have a class Dimension which I defined (like all my classes) in a file Dimension.h:

class Dimension { public:      constexpr Dimension() noexcept;      constexpr Dimension(int w, int h) noexcept;      int width;     int height;  }; 

I thought I could, like in all my classes, put the definition in a separate Dimension.cpp:

#include "Dimension.h"  constexpr Dimension::Dimension() noexcept : width(0), height(0) {}  constexpr Dimension::Dimension(int w, int h) noexcept : width(w), height(h) {} 

But when I try to use the class, the compiler tells me:

warning: inline function 'constexpr Dimension::Dimension()' used but never defined

and while linking:

undefined reference to 'pong::graphics::Dimension::Dimension()'

(same with the other constructor)

If I define the class in the header like so:

class Dimension { public:      constexpr Dimension() noexcept : width(0), height(0) {}      constexpr Dimension(int w, int h) noexcept : width(w), height(h) {}      int width;     int height;  }; 

and omit the .cpp file, everything works fine.

I'm using GCC 4.9.2. Why does separate definition not work?

like image 627
Timo Türschmann Avatar asked Dec 07 '14 17:12

Timo Türschmann


People also ask

Should constexpr be in header?

In other words, you should use constexpr for your constants in header files, if possible, otherwise const . And if you require the address of that constant to be the same everywhere mark it as inline .

Where is constexpr defined?

The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const , it can be applied to variables: A compiler error is raised when any code attempts to modify the value.

When to use #define vs constexpr?

#define (also called a 'macro') is simply a text substitution that happens during preprocessor phase, before the actual compiler. And it is obviously not typed. constexpr on the other hand, happens during actual parsing. And it is indeed typed.

Can constexpr be modified?

According to the proposal, an object created within a constexpr expression, can now be changed during the evaluation process - until the evaluation process or the object's lifetime ends.


2 Answers

If a constexpr function is not defined inside the header, the compiler can not see the definition of the constexpr functions while compiling all the other source files.

Obviously, if it can't see the definition of the functions, it can't perform the steps necessary to calculate them at compile-time. Thus all constexpr functions must be defined everywhere they are used.

Thanks @IgorTandetnik:
[dcl.constexpr] §7.1.5/2

constexpr functions and constexpr constructors are implicitly inline.

[basic.def.odr] §3.2/4

An inline function shall be defined in every translation unit in which it is odr-used.

like image 121
Timo Türschmann Avatar answered Sep 18 '22 15:09

Timo Türschmann


What you're asking can be accomplished, with a significant limitation: the constexpr function can then only be called from inside the translation unit (i.e. source file) where it is defined. This is not appropriate for the example you gave, since the constructor is meant to be part of the class' public interface. However it can be very useful in other cases, e.g. to define private methods as constexpr and then use their return values in expressions that need to be known at compile time, e.g. template instantiations, switch statement labels, etc.

like image 25
Isac Casapu Avatar answered Sep 19 '22 15:09

Isac Casapu