admin管理员组

文章数量:1279208

I'm experiencing an error on MSVC 19.43, while gcc and clang doesn't.
Here the code that I was testing on.

#include <string>
#include <memory>

template <typename T>
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<foo>{}(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.

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.

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

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./z/nhWMPW1q4

#include <string>
#include <memory>

template <typename T>
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<foo>{}(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/w/cpp/language/destructor#Implicitly-defined_destructor
https://en.cppreference/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./z/7Mz8G8rro

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

Share Improve this question asked Feb 23 at 20:19 ross1573ross1573 334 bronze badges 2
  • 2 looks like an MSVC bug, godbolt./z/rjbKPPjeK the compiler needed the destructor to be used in order to be "generated" ... – Ahmed AEK Commented Feb 23 at 20:27
  • @Ahmed thanks for the comment. I was wondering what was causing the issue, and by declaring before the constant evaluation (as in your code) solved the issue for now. – ross1573 Commented Feb 23 at 20:40
Add a comment  | 

1 Answer 1

Reset to default 0

According to the C++ standard, since std::string (in a conforming C++20 library) is supposed to have a constexpr destructor, the implicitly defined destructor of your type foo should have a constexpr. GCC and Clang's standard libraries have been updated to support this, but MSVC's STL in version 19.43 still does not mark std::string's destructor as constexpr.

本文标签: cquotexpression did not evaluate to a constantquot on implicitly defined destructorStack Overflow