How i can use plugins without vtable calls?
I write simple trait/interface Fizz:
template<typename T>
struct Fizz {
static auto do_invoke(const T &self) -> bool;
template <typename CRTP>
struct plugin {
[[nodiscard]] auto is_fizz() const {
return aa::invoke<Fizz>(*static_cast<const CRTP*>(this));
}
};
};
I can write function that use it:
// I didn't write `Buzz`. This is obvious
auto fizz_buzz(const auto& self) -> bool {
return aa::invoke<Fizz>(self) && aa::invoke<Buzz>(self);
}
I know: aa::invoke call do_invoke as static if self isn't any-like type
But i cannot call plugin ~~methods~~ functions without const_poly_ref or etc.
Is there something like poly_or_static_ref?
Heh, its interesting... You can use smth like this:
// do not works for fundamental types
template <typename T, TTA... Methods>
struct AA_MSVC_EBO static_ref : T, aa::plugin_t<Methods, static_ref<T, Methods...>>... {
static_ref() = delete;
static_ref(const static_ref&) = delete;
void operator=(const static_ref&) = delete;
};
template<TTA... Methods, typename T>
static_ref<T, Methods...>& make_static_ref(T& value) noexcept {
return static_cast<static_ref<T, Methods...>&>(value);
}
https://godbolt.org/z/Tq3ab4K6P
I try to make the smartest static or poly ref sop_ref:
struct infallible{};
template <TTA... Methods>
constexpr inline bool satisfies_v<infallible, Methods...> = true;
template <typename T, TTA... Methods>
using static_or_poly = std::variant<static_ref<T, Methods...>*, poly_ref<Methods...>>;
// static or poly
template <typename T, TTA... Methods>
struct sop_ref : plugin_t<Methods, sop_ref<T, Methods...>>... {
static_or_poly<T, Methods...> sop;
sop_ref(poly_ref<Methods...> ref) : sop(std::move(ref)) {}
sop_ref(static_ref<T, Methods...>& ref) : sop(ref) {}
sop_ref(T& ref) : sop(&make_static_ref<Methods...>(ref)) {}
};
template <TTA... Methods>
sop_ref(poly_ref<Methods...>) -> sop_ref<infallible, Methods...>;
// in `invoke_fn`
template <typename T, TTA... Methods>
result_t<Method> operator()(sop_ref<T, Methods...> p, Args... args) const {
return std::visit(/* impl */, p.sop);
}
But it doesn't make sense. C++ not have basic type infer :(
template <typename T>
auto smart_foo(aa::sop_ref<T, Foo> ref) {
return ref.foo();
}
. . .
auto val = xd{10};
// not works
smart_foo(val);
// works :(
smart_foo(aa::sop_ref<xd, Foo>(val));
Right now, I can only hope for compiler optimizations for poly_ref.
Why not use overload in this case? smart_foo(poly_ref) smart_foo(auto&&) / smart_foo(static_ref) if you want to use plugin methods
For the same reason that I want to use plugins.
self.foo() looks shorter than aa::invoke<Foo>(self)
I try to make the smartest static or poly ref
sop_ref:struct infallible{}; template <TTA... Methods> constexpr inline bool satisfies_v<infallible, Methods...> = true; template <typename T, TTA... Methods> using static_or_poly = std::variant<static_ref<T, Methods...>*, poly_ref<Methods...>>; // static or poly template <typename T, TTA... Methods> struct sop_ref : plugin_t<Methods, sop_ref<T, Methods...>>... { static_or_poly<T, Methods...> sop; sop_ref(poly_ref<Methods...> ref) : sop(std::move(ref)) {} sop_ref(static_ref<T, Methods...>& ref) : sop(ref) {} sop_ref(T& ref) : sop(&make_static_ref<Methods...>(ref)) {} }; template <TTA... Methods> sop_ref(poly_ref<Methods...>) -> sop_ref<infallible, Methods...>; // in `invoke_fn` template <typename T, TTA... Methods> result_t<Method> operator()(sop_ref<T, Methods...> p, Args... args) const { return std::visit(/* impl */, p.sop); }But it doesn't make sense. C++ not have basic type infer :(
template <typename T> auto smart_foo(aa::sop_ref<T, Foo> ref) { return ref.foo(); } . . . auto val = xd{10}; // not works smart_foo(val); // works :( smart_foo(aa::sop_ref<xd, Foo>(val));
hmm, may be i will add specialization for aa::interface_t (satisfy)
I try to make the smartest static or poly ref
sop_ref:struct infallible{}; template <TTA... Methods> constexpr inline bool satisfies_v<infallible, Methods...> = true; template <typename T, TTA... Methods> using static_or_poly = std::variant<static_ref<T, Methods...>*, poly_ref<Methods...>>; // static or poly template <typename T, TTA... Methods> struct sop_ref : plugin_t<Methods, sop_ref<T, Methods...>>... { static_or_poly<T, Methods...> sop; sop_ref(poly_ref<Methods...> ref) : sop(std::move(ref)) {} sop_ref(static_ref<T, Methods...>& ref) : sop(ref) {} sop_ref(T& ref) : sop(&make_static_ref<Methods...>(ref)) {} }; template <TTA... Methods> sop_ref(poly_ref<Methods...>) -> sop_ref<infallible, Methods...>; // in `invoke_fn` template <typename T, TTA... Methods> result_t<Method> operator()(sop_ref<T, Methods...> p, Args... args) const { return std::visit(/* impl */, p.sop); }But it doesn't make sense. C++ not have basic type infer :(
template <typename T> auto smart_foo(aa::sop_ref<T, Foo> ref) { return ref.foo(); } . . . auto val = xd{10}; // not works smart_foo(val); // works :( smart_foo(aa::sop_ref<xd, Foo>(val));
hm, why you cant change realization invoke for !any type such that it will invoke through static_ref, so you can use plugins?..
hm, why you cant change realization invoke for !any type such that it will invoke through static_ref, so you can use plugins?..
Implementation, bro))
I would like to use static and dynamic refs in one function.
I try to use static_ref with poly_ref – not works. (double inherit of plugin_t)
auto val = xd{123};
std::cout << smart_foo(aa::make_static_ref<Foo>(val)) << std::endl;
aa::poly_ref<Foo> ref = val;
std::cout << smart_foo(aa::make_static_ref<Foo>(ref)) << std::endl;
And it's too long))