Do you see a way to add associated types?
For example, it might look something like this:
template <typename T>
struct Deref {
struct Target {};
static auto do_invoke(const T&) -> Target&;
template <typename CRTP>
struct plugin {
auto deref() const {
return aa::invoke<Deref>(*static_cast<const CRTP*>(this));
}
};
};
template <typename Ptr>
struct Deref<std::shared_ptr<Ptr>> {
using Target = std::remove_extent_t<Ptr>;
static auto do_invoke(const std::shared_ptr<Ptr>& self) -> Target& {
return *self.get();
}
};
This is convenient because Self is responsible for the associated type itself. In this example, the opposite is true https://github.com/kelbon/AnyAny/blob/c4603b3959c5f8e8b9a104b09bb53025b1ff776f/examples/functional_paradigm.hpp#L22-L30
However, it doesn't work because result_t get return type from Method<aa::interface_t>, but Target is unique for all types.
This can be fixed, but for dyn call via poly_ref/any_ it will require explicit aanotation
For example, it might look something like this:
template <typename T> struct Deref { struct Target {}; static auto do_invoke(const T&) -> Target&;
May be you can require typename T::Target; But anyway you need to return same type for all, so Target need to be same for all types, so its useless. (i think rust has same requirements for Dyn traits, apart from the fact that rust has no cast to smaller requirements)
But anyway you need to return same type for all, so Target need to be same for all types, so its useless.
It's not useless. For example, any type that was written in the type_traits style can be rewritten.
In Rust and Swift, they really have more privileges. Dyn constraint really stricter.
Associated types will reverse the implementation. This helps to better perceive where this type comes from.
- outside - template param (we pass result type to get result)
- inside - associated param (we get concrete result for
Selftype)
Also compare :)
template <typename T>
struct Iterator {
struct Item {};
static auto do_invoke(const T&) -> std::optional<Item>;
template <typename CRTP>
struct plugin {
auto next() const {
return aa::invoke<Iterator>(*static_cast<const CRTP*>(this));
}
};
};
template <>
struct Iterator<MyIter> {
using Item = std::size_t;
static auto do_invoke(const MyIter& self) -> std::optional<Item> {
// impl
}
};
. . .
// i hope it works))
template<typename Item>
struct Constraints {
template <typename T>
struct iterator {
static auto do_invoke(const T&) -> std::optional<Item>;
template <typename CRTP>
struct plugin {
auto next() const {
return aa::invoke<iterator>(*static_cast<const CRTP*>(this));
}
};
};
};
template<>
struct Constraints <std::size_t> {
template<typename T>
struct iterator {
static auto do_invoke(const T&) -> std::optional<std::size_t> {
// impl
}
};
};
Although maybe it useless
Can you show how you see interfaces with template parameters?
I can do it somehow like this: godbolt
But I'm sad that I can't use Method<Self>::Type. We need to know the Type
Probably it possible with static_ref (if make it smartest), but i'm not C++ programmer to make this code work
template <typename Output>
using Oof = /* template<typename Self> Foo<Self, Output>*/;
template <typename Self, typename Output>
auto foo(aa::static_ref<Self, Oof<Output>>& ref) {
}
Can you show how you see interfaces with template parameters?
template<typename A, typename B>
struct foo {
template<typename T>
struct trait {
static X do_invoke(T& self) { return X{}; }
};
};
template<typename T>
using trait_foo_int_double = foo<int, double>::template trait;
// or
using h = any_with<foo<int, double>::template trait>;
Can you show how you see interfaces with template parameters?
template<typename A, typename B> struct foo { template<typename T> struct trait { static X do_invoke(T& self) { return X{}; } }; }; template<typename T> using trait_foo_int_double = foo<int, double>::template trait; // or using h = any_with<foo<int, double>::template trait>;
Oh, no. Here is an example from godbolt, but with this style - https://godbolt.org/z/b8jK4bPK8
Oh no, bro. When I have time, I will definitely try to make it.
Oh no, bro. When I have time, I will definitely try to make it.
I'm always happy with ideas, but it seems impossible to do something adequate here
Oh no, bro. When I have time, I will definitely try to make it.
I don't remember exactly what the discussion was, but I'm just throwing off a random thought here
template<typename T>
struct trait {
static void do_invoke(T& self);
template<typename U = T>
consteval auto associated_type() {
return std::type_identity<U::type>{};
}
};
It seems to me Trait::type will be enough. И dynamic invoking must be non erasure this type:
aa::poly_ref<Trait, aa::where_eq<Trait, ConcreateAssocType>>
And I'm not sure. Will it be consistent in the context of C++?
In addition, we have different views on the use of aa:
// I would do it like this
template <typename T>
struct draw {
struct metadata {};
static auto do_invoke(const T& self, std::span<uint8_t> buf) -> metadata;
};
struct DrawA {};
template<>
struct draw<DrawA> {
using metadata = size_t;
static auto do_invoke(const DrawA& self, std::span<uint8_t> buf) -> metadata {
// DrawA impl
}
};
struct DrawB {};
template<>
struct draw<DrawB> {
using metadata = size_t;
static auto do_invoke(const DrawB& self, std::span<uint8_t> buf) -> metadata {
// DrawA impl
}
};
// But you prefer the imperative style more
template<typename metadata>
struct draw {
template <typename T>
struct method {
static auto do_invoke(const T& self, std::span<uint8_t> buf) -> metadata;
};
};
struct DrawA {
auto draw() const {
// DrawA impl
}
};
template<>
struct draw</* metadata */ size_t> {
static auto do_invoke(const DrawA& self, std::span<uint8_t> buf) -> size_t {
self.draw();
}
};
struct DrawB {
auto draw() const {
// DrawA impl
}
};