![]() |
Boost : |
From: Jean-Louis Leroy (jl_at_[hidden])
Date: 2025-05-12 21:10:44
> Can we strip off the virtual_?
>
> struct NAME ## _overrider<...> {
> template<typename T>
> using virtual_ = T;
> ...
> };
You mean allow virtual_ in the overrider's parameters? The macro gets:
meet, (virtual_<Dog&> dog, virtual_<Cat&> cat)
...and it changes into:
meet(Dog& dog, Cat& cat)
I don't see a way of doing this while carrying the parameter's names.
> Actually, what if we make virtual a keyword handled by the macro:
>
> BOOST_OPENMETHOD(foo, (virtual T&), void)
>
> It would look something like
> #define HAS_VIRTUAL_TESTvirtual ~,~
> #define HAS_VIRTUAL_I(a, b, r, ...) r
> #define HAS_VIRTUAL(arg) HAS_VIRTUAL_I(HAS_VIRTUAL_TEST ## arg, 1, 0, ~)
> #define REMOVE_VIRTUALvirtual
> #define REMOVE_VIRTUAL(arg) REMOVE_VIRTUAL ## arg
>
> This won't quite work as is. It needs some work to adjust the order of
> macro expansion.
It took me a while to see how this could work, and now it's taking me a while to
see why it doesn't want to - see https://godbolt.org/z/16nensohc. Probably
related to your "order of expansion" comment?
It is appealing but it has problems too. Any comma in the parameter's types will
break it. YOMM2 uses Boost.PP loops over macro arguments to build the forwarding
function, so whenever there is a comma in the parameter types, you have to use
tricks like BOOST_IDENTITY_TYPE. For OpenMethod, I moved as much macro-magic to
TMP as I could.
> To get the performance benefit, virtual_ptr has to be integrated into
> the surrounding code.
Yes, I think that there will be two usage patterns: casual use of open-methods,
and open-method aware design, like the AST example using unique_virtual_ptrs.
> If we're doing that, then it should act more like a normal pointer, and the
> conversion from a reference (which makes some sense when it's being used as a
> method parameter type) is not such a good idea.
Yes, it's a dilemma. My rationalization (i.e. lie to myself) is that
virtual_ptr(snoopy) is like &snoopy, it makes a pointer from a reference.
> > By the way, do you have an opinion on allowing smart pointers as virtual
> > parameters?
> >
>
> I think it should be allowed. Can I bring my own smart pointer?
Yes.
#include <iostream>
#include <boost/openmethod.hpp>
#include <boost/openmethod/compiler.hpp>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
template<typename Class, class Policy>
struct boost::openmethod::virtual_traits<
boost::intrusive_ptr<Class>, Policy> {
using virtual_type = std::remove_cv_t<Class>;
static auto peek(boost::intrusive_ptr<Class> arg) -> const Class& {
return *arg;
}
template<class Other>
using rebind = boost::intrusive_ptr<Other>;
template<class Other>
static auto cast(const boost::intrusive_ptr<Class>& obj) {
if constexpr (detail::requires_dynamic_cast<
Class*, typename Other::element_type*>) {
return boost::dynamic_pointer_cast<
typename virtual_traits<Other, Policy>::virtual_type>(obj);
} else {
return boost::static_pointer_cast<
typename virtual_traits<Other, Policy>::virtual_type>(obj);
}
}
};
struct Node : boost::intrusive_ref_counter<Node> {
virtual ~Node() {}
};
struct Literal : Node {
explicit Literal(int value) : value(value) {}
int value;
};
BOOST_OPENMETHOD(value, (virtual_ptr<boost::intrusive_ptr<Node>>), int);
BOOST_OPENMETHOD_OVERRIDE(
value, (virtual_ptr<boost::intrusive_ptr<Literal>> node), int) {
return node->value;
}
BOOST_OPENMETHOD_CLASSES(Node, Literal)
auto main() -> int {
boost::openmethod::initialize();
boost::intrusive_ptr<Node> x = new Literal{42};
std::cout << value(x) << "\n";
return 0;
}
...and another specialization for `const intrusive_ptr<Class>&`.
I should probably make requires_dynamic_cast public.
> // BOOST_OPENMETHOD_CLASSES(int, std::any, any_policy)
> using boost::openmethod::detail::class_declaration_aux;
> class_declaration_aux<any_policy, mp_list<std::any>> x;
> class_declaration_aux<any_policy, mp_list<int, std::any>> y;
> class_declaration_aux<any_policy, mp_list<double, std::any>> z;
Smashing! And the type_erasure one too. I did not realize we were so close to
it already. Creating an issue...
> What if the slots are reserved by an abstract base that has no concrete
> derived classes? Does that situation get filtered out somewhere earlier?
Not at the moment.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk