首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有std::variant或unions的包装器的公共接口

带有std::variant或unions的包装器的公共接口
EN

Stack Overflow用户
提问于 2022-08-04 00:58:35
回答 1查看 83关注 0票数 2

这个问题与Enforcing a common interface with std::variant without inheritance有关。

这个问题和这个问题的区别在于,我不介意继承,我只是在寻找以下的结构/类.

代码语言:javascript
复制
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; } };

..。自动“组装”成模板:

代码语言:javascript
复制
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是为了使内存连续。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-04 02:00:29

您不能自动地将其设置为允许multiB.get(),但可以通过提供操作符重载来允许multiB->get()(*multiB).get()甚至隐式转换:

代码语言:javascript
复制
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);
    }
};

在使用标准库中的迭代器时,您可能遇到过这种情况。

示例:

代码语言:javascript
复制
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);
}

输出:

代码语言:javascript
复制
123123123
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73229272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档