Search code examples
c++new-operatorc++17

Calling placement new using base class


I have doubts about placement new. I would like to call Base Class constructor in class Derived method. The code should make this more clear.

Code

#include <iostream>
#include <string>
#include <type_traits>
#include <optional>


double calculate_z(int x) {
    return 2 * x;   
}

struct Base {
    int x;
    double z;

    Base(): x(0), z(0) {}
    Base(int value): x(value), z( calculate_z(x)) {}
};

class Derived: public Base {
public:
    //is this enought to make it safe? 
    static_assert( std::is_trivially_copyable<Base>::value, "Object using new in placement constructor has to be trivial!");
    std::optional<bool> force; 

    void load(int x)
    {
        new(this) Base(x); //can I call it safty? will this couse any trouble with force member? 
        // Do I need to call destructor manualy or delate? (probalby no)
        force = std::make_optional(false);
    }
};

int main()
{
    Derived a;
    a.load(5);
}

Link do online compiler

Reason

Example looks point less. But instead of Base in that class is T. Derivative is template. I need to call this constructor because I read data from JSON. And I use serialization library that required existing that object already. Not inherit from Base is a problem (because I could use Base as a member). So why I need call constructor? Because T comes from other library and not calling constructor make my app working improper.

So questions:

  1. Is my program safe?
  2. if 1 is yes, Is one traits enough to replace Base with template?
  3. if no, how I can make it safe?

Base as a member

I can't make Base as a member because I serialize this using http://uscilab.github.io/cereal/serialization_functions.html


Solution

  • What are you trying to write here? Nowhere in the link you listed does anything like this get suggested.

    It looks like what you want is:

    struct Base {
        int x;
        double z;
    
        Base(): x(0), z(0) {}
        Base(int value): x(value), z( calculate_z(x) ) {}
    };
    
    class Derived : public Base {
        std::optional<bool> force; 
    
        template<class Archive>
        void serialize(Archive & archive)
        {
            archive( x, z, force );
        }
    };
    
    class Safer {
        Base b;
        std::optional<bool> force; 
    
        template<class Archive>
        void serialize(Archive & archive)
        {
            archive( b.x, b.z, force );
        }
    };
    
    class Constructs {
        Base b;
        std::optional<bool> force; 
    
        template<class Archive>
        void load(Archive & archive)
        {
            int x, z;
            archive( x, z, force );
            b = Base( x );
            // Could be
            // b = Base( x, z );
        }
    
        template<class Archive>
        void save(Archive & archive)
        {
            archive( b.x, b.z/*???*/, force );
        }
    };