#Composition like behaviour with concepts

44 messages · Page 1 of 1 (latest)

nocturne ravine
#

due to the fact that with concepts you can specify what methods a type can have and how they behave can you fully go that route ?

the only bottleneck i see is storing said objects. inheritance also allows storing via base classes which allow you to store multiple of them inside vectors or whatever.

is there currently a way to do this in cpp?

i think rust deals with this in a similar way by storing pointers with types that implement the trait
so the same as storing ptrs of base classes but its done somewhat implicitly

atm i dont see a way of doing this

grand shoreBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

mighty bear
#

If you only need a generic function that accepts a certain interface, use concepts

#

But an alternative would be std::variant

nocturne ravine
#

hmm idk how variant would solve that

#

you would need to pre know all the possible types that respect that concept

mighty bear
#

which is why i said classic OO style is still the goto for polymorphic storage

#

any other solution is basically the same or more overhead

#

or its less overhead but its restricted

#

like a variant has much less runtime overhead, but it adds developement and compile time overhead

nocturne ravine
#

If you are doing "type erasure" like stuff you probably have no idea what you actual type is

#

So that means std::visit

#

Probably*

#

Id assume that some slight indirection is faster

mighty bear
nocturne ravine
#

Kinda slow from what i know

#

Basically ifelse

mighty bear
#

what i know for sure is msvc just generates a switch statement for up to 512 types when using std::visit

mighty bear
nocturne ravine
#

Hmm interesting

#

I was looking this up recently

#

And at least for gcc people were annoyed for being slow because of the if else thing

#

Dk if its a gcc msvc thing

#

I mainly use gcc

#

Or maybe i misunderstood the discussion idk

mighty bear
pale plank
# nocturne ravine due to the fact that with concepts you can specify what methods a type can have ...

like, you can manually do what rust does automatically for you with a trait,

  1. create a concept to check the type fulfills your interface requirements
namespace trait {

template<typename T>
concept bytestream =
    requires(      T& stream, void* buffer, usize size) { { stream.read_bytes(buffer, size) } -> std::same_as<result<void>>;  } and
    requires(      T& stream, usize position)           { { stream.seek(position)           } -> std::same_as<result<void>>;  } and
    requires(const T& stream)                           { { stream.position()               } -> std::same_as<result<usize>>; }
;

}
  1. create a virtual base class for this interface
struct model {
    model() = default;
    virtual ~model() = default;

    virtual auto read_bytes(void* buffer, usize size) -> result<void> = 0;
    virtual auto seek(usize position)                 -> result<void> = 0;
    virtual auto position() const                     -> result<usize> = 0;
};
  1. create a wrapper that stores any T that satisfies the concept, and implements the virtual functions by calling the corresponding function on the T:
template<typename T>
struct impl final : model {
    template<typename X>
    impl(X&& x) : reader{std::forward<X>(x)} {}
    auto read_bytes(void* buffer, usize size) -> result<void>   override { return reader.read_bytes(buffer, size); }
    auto seek(usize position)                 -> result<void>   override { return reader.seek(position); }
    auto position() const                     -> result<usize>  override { return reader.position(); }
    T reader;
};
  1. wrap this wrapper in a wrapper that stores a unique_ptr<model> and forwards all the functions to that one
#

but of course this is a ton of boilerplate, and doesn't compose too well;
can't just ad-hoc say "ok I need a Box<bytestream + Copy>"

#

you can go even lower of course and instead of using actual virtual functions, just build a sort of vtable yourself with structs of function pointers and templates

mighty bear
#

or just yknow use inheritance nooo

pale plank
nocturne ravine
#

I would like to note that this is not necessarily a performance or inheritance bad kinda thing

#

I was just wondering if this behaviour can be achieved. I perosnallly find composition much easier to think about sometimes

grand shoreBOT
#

@nocturne ravine Has your question been resolved? If so, type !solved :)

mighty bear
nocturne ravine
#

Arent they the same or similar implementation underneath ?

nocturne ravine
#

Whats the saying

#

Something simething different coat