Info
-
Did you know about
virtual
inheritance in C++?
Example
struct A {
int a{};
};
struct B : virtual A {};
struct C : virtual A {};
struct D : B, C {};
int main() {
D d{};
d.a = {}; // without virtual -> request for member 'a' is ambiguous
}
Puzzle
template <class... Ts>
struct interface; // TODO
template <auto... Vs>
struct implementation final; // TODO
#include <https://raw.githubusercontent.com/boost-ext/ut/v1.1.9/include/boost/ut.hpp>
int main() {
using namespace boost::ut;
"virtual type_list interface empty"_test = [] {
auto impl = implementation<>{};
const interface<>& i = impl;
};
"virtual type_list interface single"_test = [] {
auto impl = implementation<int{42}>{};
const interface<int>& i = impl;
expect(42 == i.on(int{}));
};
"virtual type_list interface multi"_test = [] {
auto impl = implementation<int{4}, double{2.}, float{42.f}>{};
const interface<int, double, float>& i = impl;
expect(4 == i.on(int{}));
expect(2. == i.on(double{}));
expect(42.f == i.on(float{}));
};
}
Solutions
template <class... Ts>
struct interface {
public:
template <class T>
const T& on(T) const {
return std::get<T>(vs);
}
protected:
constexpr explicit interface(auto&&... args) : vs(args...) {}
private:
std::tuple<Ts...> vs;
};
template <auto... Vs>
struct implementation final : interface<decltype(Vs)...> {
constexpr explicit implementation() : interface<decltype(Vs)...>(Vs...) {}
};
template <class... Ts>
struct interface : virtual interface<Ts>... {
using interface<Ts>::on...;
};
template <class T>
struct interface<T> {
virtual T on(T) const = 0;
virtual ~interface() noexcept = default;
};
template <auto... Vs>
struct implementation : interface<decltype(Vs)...>, implementation<Vs>... {};
template <auto V>
struct implementation<V> : virtual interface<decltype(V)> {
using T = decltype(V);
T on(T) const { return V; }
};
template <class... Ts>
struct interface : virtual interface<Ts>... {
using interface<Ts>::on...;
};
template <class T>
struct interface<T> {
virtual T on(T) const = 0;
};
template <auto... Vs>
struct implementation final : implementation<Vs>...,
interface<decltype(Vs)...> {};
template <auto V>
struct implementation<V> : virtual interface<decltype(V)> {
using T = decltype(V);
T on(T) const override { return V; }
};