I am concerned about the following framework, especially the magic inside the register_property_
helper classes which determines the pointer to an embedding object instance when given a pointer to one of its members. Does this implementation use undefined behavior? If so, how could i rewrite the implementation to be fully standard compliant?
#include <any>
#include <map>
#include <iostream>
#include <memory>
#include <string>
// FRAMEWORK
class object
{
public:
std::any& operator[] (std::string name) { return *_properties.at (name); }
std::any const& operator[] (std::string name) const { return *_properties.at (name); }
protected:
void register_property (std::string name, std::any& property)
{
_properties[name] = std::addressof (property);
}
private:
std::map<std::string, std::any*> _properties;
};
#define REGISTER_PROPERTY(name, member) \
struct register_property_ ## name \
{ \
register_property_ ## name () { self ()->register_property (# name, self ()->member); } \
register_property_ ## name (register_property_ ## name const&) { self ()->register_property (# name, self ()->member); } \
register_property_ ## name& operator= (register_property_ ## name const&) = default; \
register_property_ ## name (register_property_ ## name &&) { self ()->register_property (# name, self ()->member); } \
register_property_ ## name& operator= (register_property_ ## name &&) = default; \
\
private: \
self_type* self () \
{ \
return reinterpret_cast<self_type*> (reinterpret_cast<std::byte*> (this) - offset_to_self ()); \
} \
static ptrdiff_t offset_to_self (self_type* ptr = nullptr) \
{ \
return reinterpret_cast<ptrdiff_t> (std::addressof (ptr->register_property_ ## name ## _)) - reinterpret_cast<ptrdiff_t> (ptr); \
} \
} register_property_ ## name ## _
// CLIENT USE CASE
auto make_unique_object () -> std::unique_ptr<object>
{
class foo_object
: public object
{
std::any _width;
std::any _height;
using self_type = foo_object;
REGISTER_PROPERTY(Width, _width);
REGISTER_PROPERTY(Height, _height);
};
return std::make_unique<foo_object> ();
}
int main ()
{
auto object = make_unique_object ();
(*object)["Height"] = 50;
std::cout << "Object heigth is " << std::any_cast<int> ((*object)["Height"]) << '\n';
}
Aucun commentaire:
Enregistrer un commentaire