dav
dav

Reputation: 936

Unable to manually call destructor of std::string

I'm experimenting with unions and made this example class A with anonymous union member. Since the union contains a std::string and a std::vector I needed to define a destructor for the class. But, when I try to manually call ~string() I get

union.cpp: In destructor 'A::~A()':
union.cpp:14:14: error: expected class-name before '(' token
    s_.~string();

I don't get this with the vector. If I remove the call to s._~string(); it compiles fine. Is this a compiler bug? I'm using MinGW64.

#include <string>
#include <vector>

class A
{
    public:
    explicit A(const std::string &s) : s_ {s}, is_string {true} {}
    explicit A(const std::vector<int> &v) : v_ {v}, is_string {false} {}

    ~A()
    {
        if (is_string)
            s_.~string();
        else
            v_.~vector();
    }

    private:
    union
    {
        std::string s_;
        std::vector<int> v_;
    };
    bool is_string;

};

int main()
{
    A a("Hello, World!");
    return 0;
}

Using std::delete_at(std::addressof(s_)) does work with -std=c++17. What's going on here?

Upvotes: 6

Views: 1768

Answers (2)

hochl
hochl

Reputation: 12950

I just had the same problem, and the following worked for me:

typedef std::string string_alias;
sp->~string_alias();

It seems the C++ compiler is confused by the ~std::string part of the statement.

Upvotes: 2

user6556709
user6556709

Reputation: 1270

std::string is not a real type but a typedef.

using std::string = std::basic_string<char>;

So you need to call basic_string destructor.

~A()
{
    if (is_string)
        s_.~basic_string();
    else
        v_.~vector();
}

Upvotes: 6

Related Questions