Constexpr classes objects can be created and evaluated at compile time. As we have the knowledge of creating constexpr aggregates, let’s apply the same knowledge here and try creating a constexpr class.
#include <iostream>
class Point
{
private:
int m_x{};
int m_y{};
public:
Point() = default;
Point(int x, int y)
: m_x{x}, m_y{y}
{
}
void print() const
{
std::cout << "Point(" << m_x << ", " << m_y << ")\n";
}
constexpr int greaterCoordinate() const
{
return m_x < m_y ? m_y : m_x;
}
};
int main(int argc, char const *argv[])
{
constexpr Point p{1, 2};
p.print();
constexpr int greater{p.greaterCoordinate()};
std::cout << "Greater coordinate: " << greater << "\n";
return 0;
}We have declared the Point object with constexpr and declared a constexpr greaterCoordinate member function. Let’s compile the program. When I compiled the program, I got following compilation error on my machine:
constexpr_classes.cpp: In function 'int main(int, const char**)':
constexpr_classes.cpp:28:27: error: call to non-'constexpr' function 'Point::Point(int, int)'
28 | constexpr Point p{1, 2};
| ^
constexpr_classes.cpp:11:5: note: 'Point::Point(int, int)' declared here
11 | Point(int x, int y)
I think is very clear why compiler is crying. It is saying that call to Point(int,int) constructor is made which is non-constexpr function.
Note
On the resource that I am following, author mentioned a different error of class not being a literal type. Not sure why compiler is not throwing the same error for me. I have tried different C++ standards with
g++compiler.
Let’s declare constructor as constexpr.
#include <iostream>
class Point
{
private:
int m_x{};
int m_y{};
public:
Point() = default;
constexpr Point(int x, int y)
: m_x{x}, m_y{y}
{
}
void print() const
{
std::cout << "Point(" << m_x << ", " << m_y << ")\n";
}
constexpr int greaterCoordinate() const
{
return m_x < m_y ? m_y : m_x;
}
};
int main(int argc, char const *argv[])
{
constexpr Point p{1, 2};
p.print();
constexpr int greater{p.greaterCoordinate()};
std::cout << "Greater coordinate: " << greater << "\n";
return 0;
}Now it should compiler successfully and run.
Note
In C++11, non-static constexpr member functions are const implicitly (except constructors). In C++14 (and onwards), constexpr member functions are not implicitly const. We need to explicitly make them const.
Furthermore, implicitly defined constructors are constexpr. For example,
class Pair
{
};
int main(int argc, char const *argv[])
{
constexpr Pair p{}; // should work
return 0;
}We created an empty class and it should have implicit default constructor. So, initializing this empty class in constexpr context works.