"expression did not evaluate to a constant" on implicitly defined destructor
14:31 23 Feb 2025

I'm experiencing an error on MSVC 19.43, while gcc and clang doesn't.
Here the code that I was testing on.
https://godbolt.org/z/nhWMPW1q4

#include 
#include 

template 
struct deleter {
    constexpr void operator()(T* ptr) {
        delete ptr;
    }
};

struct foo {
    std::string str;

    constexpr foo() = default;
    constexpr foo(std::string const& s) : str(s) {}
    constexpr foo(std::string&& s) : str(std::move(s)) {}
};

struct bar {
    foo* ptr;

    constexpr bar() : ptr(nullptr) {}
    constexpr bar(foo* p) : ptr(p) {}
    constexpr ~bar() { deleter{}(ptr); }
};

constexpr int func() {
    bar(new foo());
    return 5;
}

int main() {
    static_assert(func() == 5);
}

According to cppreference, the implicitly defined destroyer is constexpr if it meets the requirements.
https://en.cppreference.com/w/cpp/language/destructor#Implicitly-defined_destructor
https://en.cppreference.com/w/cpp/language/constexpr#constexpr_destructor

On top of the requirements of constexpr functions, a destructor also needs to satisfy all following conditions to be constexpr-suitable:

For every subobject of class type or (possibly multi-dimensional) array thereof, that class type has a constexpr destructor.(until C++23)
The class does not have any virtual base class.

Now that std::string is constexpr, I thought that the implicitly defined destructor of foo should have a constexpr destructor. However, the MSVC compiler is saying that the destructor of foo is not marked as constexpr.

And when I added another bar that uses delete on destructor, MSVC suddenly becomes happy with the code.
https://godbolt.org/z/7Mz8G8rro

Is this a bug in MSVC or am I missing something from the standard?

c++