Hi everybody.
I've been following the work on
P1858 and just yesterday it occurred to me that it'd be useful to do something like this:
template <typename... Ts>
rtype<Ts> func(ptype<Ts>) ... = 0;
template <typename... Ts>
struct Implementation: Interface<Ts...>
rtype<Ts> func(ptype<Ts> p) override
where rtype<>, ptype<> and impl<> are fictional templates with exposition-only purpose.
At the moment such a construct is possible via recursive inheritance, with much added boilerplate and unneeded RTTI information being written out in the resulting binary (for the intermediate, not used types). Following is a possible implementation of the above, given the current tools at our disposal.
template <typename... Ts>
virtual rtype<T> func(ptype<T>) = 0;
template <typename T, typename... Ts>
struct Interface<T, Ts...>: Interface<Ts...>
using Interface<Ts...>::func;
virtual rtype<T> func(ptype<T>) = 0;
template <typename Interface, typename... Ts>
template <typename Interface>
struct Implementation<Interface>: Interface
template <typename Interface, typename T>
struct Implementation<Interface, T>: Interface
rtype<T> func(ptype<T> p) override
template <typename Interface, typename T, typename... Ts>
struct Implementation<Interface, T, Ts...>: Implementation<Interface, Ts...>
using Implementation<Interface, Ts...>::func;
rtype<T> func(ptype<T> p) override
template <typename... Ts>
using Implementation = detail::Implementation<Interface<Ts...>, Ts...>;
An alternative version of the above can be implemented with the help of std::variant, but with the limitation that all rtype<Ts>... must be the same, and with the speed penalty that a sub optimized variant can incur. Here's a possible implementation:
template <typename... Ts>
using variant_type = std::variant<ptype<Ts>...>;
using return_type = std::tuple_element_t<0, std::tuple<rtype<Ts>...>>;
static_assert(std::conjunction_v<std::is_same<return_type, rtype<Ts>>...>, "return types must be the same for all functions. Sigh.");
virtual return_type func(variant_type const &) = 0;
template <typename... Ts>
struct Implementation: Interface<Ts...>
using Interface<Ts...>::variant_type;
using Interface<Ts...>::return_type;
return_type func(variant_type const &v) override
return std::visit([](auto p){ return impl<decltype(p)>(); }, v);
struct Implementation<>: Interface<>
At the moment I'm using the std::variant approach in some production code, for it's less verbose than the recursive approach and I can cope with its limitations, but I believe it'd be nice to use the generalized pack syntax for that.
All the above considered, I'd therefore like to suggest an amendment to P1858 as described in the first code snippet.
Fabio Alemagna