首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用可变模板对std::variant进行std::variant访问?

如何使用可变模板对std::variant进行std::variant访问?
EN

Stack Overflow用户
提问于 2020-10-28 09:21:30
回答 1查看 144关注 0票数 2

我正在尝试写一个逻辑,使用命令和工厂模式。基于std::variant中的数据,我想创建一个对象。它可能看起来像C++类型的映射。

下面是代码:Wandbox

我可以硬编码所有使用过的类型,但是我想用可变模板实现自动化,该怎么做呢?

代码语言:javascript
复制
#include <cassert>
#include <variant>
#include <type_traits>
#include <memory>
#include <iostream>


struct IFace
{
    virtual void foo() = 0;
};

template<typename TKey, typename TValue>
struct Base : IFace
{
    using Key = TKey;
    using Value = TValue;
};

struct Int : Base<int, Int>
{
    void foo() override { std::cout << "Int"; }
};

struct Double : Base<double, Double>
{
    void foo() override { std::cout << "Double"; }
};

using Var = std::variant<int, double>;

template<typename ...Args>
std::shared_ptr<IFace> factory(const Var& v)
{
    std::shared_ptr<IFace> p;

    std::visit([&p](auto&& arg){
        using TKey = std::decay_t<decltype(arg)>;
        // TODO: use variadic instead of hardcoded types
        if constexpr (std::is_same_v<TKey, int>)
        {
            using TValue = typename Base<TKey, Int>::Value;
            p = std::make_shared<TValue>();
            std::cout << "int ";
        }
        else if constexpr (std::is_same_v<TKey, double>)
        {
            using TValue = typename Base<TKey, Double>::Value;
            p = std::make_shared<TValue>();
            std::cout << "double ";
        }
    }, v);

    return p;
}


int main()
{
    const Var v = 42;
    auto p = factory<Int, Double>(v);

    assert(p != nullptr);
    p->foo();

    return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-28 10:31:07

这个流行的小“重载”类对于将lambda传递给std::visit总是很有用的

代码语言:javascript
复制
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

然后,不用使用泛型lambda并试图从参数类型推断出正确的对象类型,只需为每个Args生成一个重载即可。

代码语言:javascript
复制
template<typename ...Args>
std::shared_ptr<IFace> factory(const std::variant<typename Args::Key...>& v)
{
    return std::visit(overloaded { 
        [](const typename Args::Key&) -> std::shared_ptr<IFace> { return std::make_shared<Args>(); }... 
    }, v);
}

演示:https://godbolt.org/z/nKGf3c

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64565160

复制
相关文章

相似问题

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