首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从variant<C,B>分配variant<A,B,C>?

从variant<C,B>分配variant<A,B,C>?
EN

Stack Overflow用户
提问于 2017-06-29 12:51:20
回答 2查看 140关注 0票数 3

使用=不起作用。

我有这样的代码,但它有点难看。

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

using namespace std;

namespace detail {
    template<typename... L, typename... R>
    void VariantAssignRec(variant<L...>* lhs, const variant<R...>&rhs, size_t rhs_idx, std::integral_constant<int, -1>) {
    }

    template<typename... L, typename... R, int get_idx>
    void VariantAssignRec(variant<L...>* lhs, const variant<R...>&rhs, size_t rhs_idx, std::integral_constant<int, get_idx> = {}) {
        assert(rhs_idx < std::variant_size_v< variant<R...>>);
        if (get_idx == rhs_idx) {
            cout << "assigning from idx " << get_idx << endl;
            *lhs = std::get<get_idx>(rhs);
            return;
        }
        else {
            std::integral_constant<int, get_idx - 1> prev_get_idx;
            VariantAssignRec(lhs, rhs, rhs_idx, prev_get_idx);
        }
    }
}
template<typename... L, typename... R>
void VariantAssign(variant<L...>* lhs, const variant<R...>&rhs) {
    detail::VariantAssignRec(lhs, rhs, rhs.index(), std::integral_constant<int, std::variant_size_v<variant<R...>>-1>{});
}


int main()
{
   std::variant<int, char, std::string> va = 'a';
   std::variant<std::string, int> vb = string("abc");
   cout << "va index is  " << va.index() << endl; 
   cout << "vb index is  " << vb.index() << endl; 
   VariantAssign(&va, vb);
   cout << "va index now should be 2, and it is  " << va.index() << endl; 
   vb = 47;
   VariantAssign(&va, vb);
   cout << "va index now should be 0, and it is  " << va.index() << endl; 
}

我使用VS,所以没有if constexpr,但我正在寻找通用的C++17解决方案,而不管VC++缺乏支持。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-29 22:14:54

只需使用访问者:

代码语言:javascript
复制
std::variant<A, B, C> dst = ...;
std::variant<B, C> src = B{};

std::visit([&dst](auto const& src) { dst = src; }, src);

如果src中有一个类型不能赋值给dst,那么它就不会编译--这可能是我们想要的行为。

如果您最终不经常使用此模式,则可以将赋值器移到它自己的函数中:

代码语言:javascript
复制
template <class T>
auto assignTo(T& dst) {
    return [&dst](auto const& src) { dst = src; };
}

std::visit(assignTo(dst), src);
票数 6
EN

Stack Overflow用户

发布于 2017-06-29 16:54:27

您可以使用访问者:

代码语言:javascript
复制
struct overload_priority_low{};
struct overload_priority_high : overload_priority_low{};

template <typename V>
struct AssignTo
{
private:
    V& v; 

public:
    explicit AssignTo(V& v) : v(v) {}

    template <typename T>
    void operator () (T&& t) const
    {
        assign(std::forward<T>(t), overload_priority_high{});   
    }

private:

    template <typename T>
    auto assign(T&& t, overload_priority_high) const
    -> decltype(this->v = std::forward<T>(t), void())
    {
        v = std::forward<T>(t);
    }

    template <typename T>
    void assign(T&& t, overload_priority_low) const
    {
        throw std::runtime_error("Unsupported type");
    }

};

使用用法:

代码语言:javascript
复制
int main() {
    std::variant<int, char> v = 0;
    std::variant<int, char, std::string> v2 = 42;

    std::visit(AssignTo(v), v2);
}

Demo

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

https://stackoverflow.com/questions/44816579

复制
相关文章

相似问题

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