![]() |
Boost : |
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2025-05-12 23:14:08
AMDG
On 5/12/25 3:10 PM, Jean-Louis Leroy via Boost wrote:
>> 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.
>
The above would make virtual_ into an alias that just expands to its
argument, but this only works when virtual_ is used unqualified.
>> <snip>
>
> 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.
Not necessarily. You snipped the trick I proposed to deal with that.
> 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.
>
#define HAS_VIRTUAL_TESTvirtual ~,~
#define HAS_VIRTUAL_II(a, b, r, ...) r
#define HAS_VIRTUAL_I(...) HAS_VIRTUAL_II(__VA_ARGS__)
#define HAS_VIRTUAL(arg) HAS_VIRTUAL_I(HAS_VIRTUAL_TEST ## arg, 1, 0, ~)
#define REMOVE_VIRTUALvirtual
#define REMOVE_VIRTUAL(arg) REMOVE_VIRTUAL ## arg
#define IDENTITY(arg) arg
#define MARK_VIRTUAL(arg) boost::openmethod::detail::virtual_next,
REMOVE_VIRTUAL ## arg
#define REMOVE_IF_VIRTUAL(arg) \
BOOST_PP_IIF(HAS_VIRTUAL(arg), REMOVE_VIRTUAL, IDENTITY)(arg)
#define MARK_IF_VIRTUAL(arg) \
BOOST_PP_IIF(HAS_VIRTUAL(arg), MARK_VIRTUAL, IDENTITY)(arg)
MARK_IF_VIRTUAL(virtual test)
REMOVE_IF_VIRTUAL(virtual test)
MARK_IF_VIRTUAL(nonvirtual)
REMOVE_IF_VIRTUAL(nonvirtual)
With this
(virtual B, int, virtual C), void
becomes
void(boost::openmethod::detail::virtual_next, B, int,
boost::openmethod::detail::virtual_next, C)
which can be turned into void(virtual_<B>, int, virtual_<C>) by TMP. In
the function definition, we simply remove the virtual, and everything
else, including the argument name is preserved.
The main problem is that it blows up when a comma is followed by
something that can't be token pasted:
(::global, templ<I, (X + Y)>)
In Christ,
Steven Watanabe
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk