[英]Enforcing a common interface with std::variant without inheritance
[英]Common interface with a wrapper around std::variant or unions
这个问题与Enforcing a common interface with std::variant without inheritance 有关。
这个问题和这个问题之间的区别在于,我不介意 inheritance,我只是在寻找以下结构/类......
struct Parent { virtual int get() = 0; };
struct A : public Parent { int get() { return 1; } };
struct B : public Parent { int get() { return 2; } };
struct C : public Parent { int get() { return 3; } };
...自动“组装”成模板:
template<typename PARENT, typename... TYPES>
struct Multi
{
// magic happens here
}
// The type would accept assignment just like an std::variant would...
Multi<Parent, A, B, C> multiA = A();
Multi<Parent, A, B, C> multiB = B();
Multi<Parent, A, B, C> multiC = C();
// And it would also be able to handle virtual dispatch as if it were a Parent*
Multi<Parent, A, B, C> multiB = B();
multiB.get(); // returns 2
这可能吗? 如果是这样,怎么做? 我想避免处理指针,因为使用 std::variant/unions 旨在使 memory 连续。
您不能自动将其设置为允许multiB.get()
,但您可以通过提供运算符重载来允许multiB->get()
或(*multiB).get()
甚至隐式转换:
template<typename Base, typename... Types>
struct Multi : std::variant<Types...>
{
using std::variant<Types...>::variant;
operator Base&() { return getref<Base>(*this); }
Base& operator*() { return static_cast<Base&>(*this); }
Base* operator->() { return &static_cast<Base&>(*this); }
operator const Base&() const { return getref<const Base>(*this); }
const Base& operator*() const { return static_cast<const Base&>(*this); }
const Base* operator->() const { return &static_cast<const Base&>(*this); }
private:
template<typename T, typename M>
static T& getref(M& m) {
return std::visit([](auto&& x) -> T& { return x; }, m);
}
};
在使用标准库中的迭代器之前,您可能已经遇到过这种情况。
例子:
int main()
{
Multi<Parent, A, B, C> multiA = A();
Multi<Parent, A, B, C> multiB = B();
Multi<Parent, A, B, C> multiC = C();
// Dereference
std::cout << (*multiA).get();
std::cout << (*multiB).get();
std::cout << (*multiC).get();
// Indirection
std::cout << multiA->get();
std::cout << multiB->get();
std::cout << multiC->get();
// Implicit conversion
auto fn = [](Parent& p) { std::cout << p.get(); };
fn(multiA);
fn(multiB);
fn(multiC);
}
Output:
123123123
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.