Skip to content

Latest commit

 

History

History
72 lines (53 loc) · 2.1 KB

constructor.md

File metadata and controls

72 lines (53 loc) · 2.1 KB

Meta type constructor (tkConstructor)

Template metapp::Constructor is used to create a constructor.

template <typename T>
struct Constructor
{
};

T is the constructor function prototype, the return type must be the class.

Assume we have DcClass,

class DcClass
{
public:
  DcClass(const std::string &, const int) {}

  std::string greeting(const std::string & message) {
    return "Hello, " + message;
  }
};

Then we can have,

metapp::Variant ctor = metapp::Constructor<DcClass (const std::string &, const int)>();

Then we can call the constructor, a constructor is a callable which always allocates an object and returns the instance pointer.

metapp::Variant instance(metapp::callableInvoke(ctor, nullptr, "hello", 5));

Now instance contains a pointer to DcClass, we can use it to invoke any functions in DcClass, for example,

ASSERT(instance.get<DcClass *>()->greeting("metapp") == "Hello, metapp");

Since instance only contains a pointer, so the Variant doesn't manage the instance lifetime, and it doesn't free the instance. We must delete the instance explicitly.

delete instance.get<DcClass *>();

Explicitly deleting is not elegant nor exception safe. We can use Variant::takeFrom to convert the instance pointer to a Variant managed object.

metapp::Variant object = metapp::Variant::takeFrom(metapp::callableInvoke(ctor, nullptr, "hello", 5));

Now object contains a DcClass object (not pointer), and when object is freed, the DcClass object is freed too, so we don't need to delete the object.
To call greeting(), we can write,

ASSERT(object.get<DcClass &>().greeting("world") == "Hello, world");

One may wonder why invoking a constructor doesn't return a Variant that manages the memory of the created instance. The reason is, if the constructor returns Variant that owns the instance, then there is no way to take away the ownership from the Variant, then the created object can't be managed by other mechanism such as a std::unique_ptr.