0

Will the compiler auto generate copy/move functions if the Destructor of an otherwise trivial class is declared in the .hpp file and implemented as =default in the .cpp file?

//header
class ForwardDeclaredClass;

class TrivialClass
{
public:
    ~TrivialClass();
private:
    std::shared_ptr<ForwardDeclaredClass> m_data;
};

//cpp file
TrivialClass::~TrivialClass() = default;

Our company has a guideline that enforces heavy use of forward declarations. This also forces us to forward declare the dtor and implement it in the .cpp. In addition to all other drawbacks of this guideline, do we also lose auto generate copy/move-assignment-operators and copy/move-constructors? From my understanding the compiler first sees a seemingly user defined dtor which would lead to the deletion of every copy/move function. Will the TrivialClass::~TrivialClass() = default; definition revert that deletion?

I tried to keep this question as precise and concise as possible, but feel free to make suggestions for re-formatting or re-writing. Thank you and best regards

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
Timosa
  • 1
  • 1
    @ChrisMM What? According to [cppreference](https://en.cppreference.com/w/cpp/language/move_constructor#Implicitly-declared_move_constructor) a user-declared destructor will prevent the implicit generation of a move constructor. – Nathan Pierson Mar 04 '22 at 16:15
  • The move operations will not be implicitly declared if any destructor is user-declared at all, no matter whether the definition is in the class, outside of it, or even if it is defaulted and trivial. Follow the rule-of-zero/five and either do not declare a destructor at all or explicitly define/default all special member functions. – user17732522 Mar 04 '22 at 16:17
  • Also, there is generally a difference between defaulting inside the class definition and outside of it. You should do the former. If you default outside the class, the function will not be considered trivial. – user17732522 Mar 04 '22 at 16:23
  • Well trying was way to obvious ^^. Apparently they are not deleted. My confusion stemmed from cppreference: Implicitly-declared move constructor *** If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true: there is no user-declared destructor. Sry for bloating SO a bit more. :-( Hope this helps somebody in the future anyways. :-) Thank you for the replies! – Timosa Mar 04 '22 at 16:24
  • @Timosa "Apparently they are not deleted.": The implicit move operations are not declared at all. Note that using `std::is_move_constructible` and similar is not a valid way to check this. The traits only check that construction from a rvalue is possible (which also works via the copy constructor usually). – user17732522 Mar 04 '22 at 16:26
  • Thank you everybody for this nice explanation! :-) I confused not-declared with deleted. However the result seems to be similar I guess: they are not usable. Now I will have to do some convincing-work in my company. :-) Have a great day guys! – Timosa Mar 04 '22 at 16:34
  • Yes, I think that's a good idea. It seems a heavy-handed and rather pointless rule to me, with a number of potential disadvantages. In addition to the problem being discussed here, it makes it difficult for the compiler to inline small functions which you might otherwise - for entirely legitimate reasons - elect to implement in the header file. (OK, there is such a thing as link-time optimisation, but you might not be using it and it slows down link times and generates a lot of intermediate build products also). Plus, for templates, you have no choice, so you might as well go with the flow. – Paul Sanders Mar 04 '22 at 16:44

0 Answers0