r-lyeh-archived / kult

:crystal_ball: Lightweight entity/component/system library (C++11)
zlib License
128 stars 5 forks source link

Cannot create a component without copy semantics. #5

Open WarlockD opened 8 years ago

WarlockD commented 8 years ago

I wanted to create a compoent as such:

kult::component<'ptr', std::unique_ptr<Renderable>> krenderable

The problem is that a unique_ptr is not copyable so the template fails on the merge method within the component. I create a template hack so that when it runs merge it just uses the default constructor.

... somwhere above eveything
struct _default_create {};
struct _can_copy : _default_create {};
template<class B>
    typename std::enable_if<std::is_default_constructible<B>::value>::type
        inline _assign(B& l, B&, _default_create) {
    l = B();
}

template<class B>
typename std::enable_if<std::is_copy_assignable<B>::value>::type
    inline _assign(B& l, B& r, _can_copy) {
    l = r;
}

... changing the merge in enity
virtual void merge(const type &dst, const type &src) const {
    //add<component>(dst) = T(get<component>(src));
    _assign(add<component>(dst), get<component>(src), _can_copy());
}

It will still throw errors if you cannot copy AND its not default construable. To be honest I think you should have copy semantics. I built a unique_ptr container that takes a template abstract class and derived class that does this, but I thought I post the hack I made.

The only other way I can think of doing this is having the component object store std::function of copy/move/constructor/deconstructor. I now see why unique_ptr carries around a separate deconstructor now.

r-lyeh-archived commented 8 years ago

I understand the concerns and there are fair tbh; however, before messing up with the c++11 specifics... have you tried with kult::component<'ptr', shared_ptr<>> instead?

WarlockD commented 8 years ago

I wanted to avoid using the shard_ptr as much as I can. I mean I should use it more, but my ocd doesn't like using it when I know there will only be one strong reference. Of course, speaking of references.

I just discovered std::reference_wrapper and std::ref and this works just fine. Would of saved me a few days of fiddling with templates. My whole problem is that I want to use some kind of base class to handle the delivery of vertices. Like a shape object delivers triangles differently than an object that carry's font glyphs. This all might be me as I am still in the mind set of using an uber node object and just inheriting everything from that.