c++constantsconstexpr

Are empty structs constant expressions?


The following code compiles on all the compilers that I tested so far:

struct Alignment {
    struct Center {
        constexpr Center() {}
    };
    static const Center CENTER;
};

constexpr int foo(Alignment::Center) {
    return 42;
}

constexpr int x = foo(Alignment::CENTER);

Note that Alignment::CENTER isn't constexpr here. It doesn't even have a definition, only a declaration. Yet I'm using it as an argument to foo to compute the constexpr variable x.

As soon as I add a member to Alignment::Center, it fails to compile:

struct Center {
    int n;
    constexpr Center(): n(0) {}
};

Is the first example actually valid according to the C++ standard? What exactly are the rules here? Does the standard guarantee that empty structs are always constant expressions?

EDIT:

As this answer made me realize, adding a constexpr copy constructor to Center actually makes the second example compile, so it has nothing to do with Center being empty:

struct Center {
    int n;
    constexpr Center(): n(0) {}
    constexpr Center(const Center&): n(0) {}
};

Solution

  • The defaulted copy constructor copies every (direct) base class and (direct) data member. So for your class it is similar to:

    constexpr Center::Center(const Center& other) noexcept {}
    

    There are no members or bases to copy. Since other isn't actually read, it doesn't need to have a constant value.

    And the lvalue Alignment::CENTER is a constant expression (i.e, you can store its address in a constexpr variable), so it is perfectly fine to use as a reference in constant expressions. As long as you don't try to actually read it like std::bit_cast<char>(Alignment::CENTER).

    It's similar to how this works:

    extern std::vector<int> v;
    
    constexpr int f(bool read, std::vector<int>& v) {
        return read ? v.size() : 4;
    }
    static_assert(f(false, v) == 4);  // v is not read, so it is a c
    // static_assert(f(true, v));  // Not a constant expression, v is read