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.

Resources

  1. https://www.learncpp.com/cpp-tutorial/constexpr-aggregates-and-classes/