Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why having both default destructor and vector member prevents class to be "nothrow movable constructible"?

Given the following code:

#include <iostream>
#include <vector>
#include <type_traits>

class Test {
public:
    ~Test() = default;
    std::vector<int> m_vector;
};


int main() {
    std::cout << std::is_nothrow_move_constructible_v<Test> << std::endl;
    return 0;
}

It outputs 0, meaning the Test class can't be "nothrow moved". However, if I remove either ~Test() or m_vector then it returns 1.

How to explain this please?

For reference, I'm using clang++-7 with C++17.

like image 509
Delgan Avatar asked Nov 24 '25 20:11

Delgan


2 Answers

See [class.copy.ctor]/8:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if [other conditions omitted, and] X does not have a user-declared destructor.

Thus, the Test class only has a copy constructor, not a move constructor. Any code that uses a Test rvalue to initialize a new Test object will use the copy constructor, which is not noexcept because of the vector member. If the vector member is removed, the copy constructor of Test will become trivial.

like image 189
Brian Bi Avatar answered Nov 26 '25 09:11

Brian Bi


When you define a user declared destructor, the class will not have an implicitly generated move constructor. Hence, moving will invoke copy constructor. The copy constructor of std::vector is potentially throwing, hence the implicit copy constructor of Test will also be potentially throwing.

like image 25
eerorika Avatar answered Nov 26 '25 08:11

eerorika