c++ boost spirit x3 variant递归分配问题

xzv2uavs  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(114)

在特殊情况下
我有一个数据结构

namespace x3 = boost::spirit::x3;
struct one;
struct two : x3::variant<x3::forward_ast<one>,int>{
    using base_type::base_type;
    using base_type::operator=;
    two& operator=(const std::string& rhs){
        return *this;
    }
    two& operator=(const std::string&& rhs){
        return *this;
    }
};
struct one :  x3::variant<boost::recursive_wrapper<two>,std::string>{
    using base_type::base_type;
    using base_type::operator=;
};

在这种情况下,分配是可以的

one  on{"sssss"};
two  wo{22};
wo = 123;
on = std::string("vvvvvvvvvvv");
on = wo;

但是当我直接将一个字符串赋给wo时,它会提示一个错误:

wo = on;
// wo = one("sadfasdfas"); //You can't do this
wo = std::string("sadfasdfas"); <----【/usr/local/include/boost/variant/variant.hpp:2172:14: Candidate function not viable: no known conversion from 'std::string' to 'boost::variant<boost::spirit::x3::forward_ast<one>, int>' for 1st argument】

我已经重载了相关函数,但似乎没有效果。谁知道这是为什么,并告诉我如何作出正确的修改

tgabmvqs

tgabmvqs1#

问题是,您为const std::string&const std::string&&重载了two::operator=,这两个都不是使用(非常量)右值参数std::string("vvvvvvvvvvv")进行重载解决的最佳匹配。相反,最佳匹配来自using base_type::operator=中包含的x3::variant::operator=(T&&)source):

template <typename T, class = non_self_t<T>>
 variant& operator=(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable<variant_type, T&&>::value))
 {
     var = std::forward<T>(rhs);
     return *this;
 }

var = std::forward<T>(rhs);导致了你提到的编译错误(var是不能赋值字符串的boost::variant<boost::spirit::x3::forward_ast<one>, int>)。
为了让你的重载像预期的那样工作,你可以让你的右值赋值操作符接受非常量的右值引用,使它在重载解析中比模板化的operator=具有更高的优先级(并且实际上使它能够充分实现,因为你无论如何都不能从const std::string&&移动):

two& operator=(std::string&& rhs) {
    return *this;
}

godbolt
请注意,您不需要在one by boost::recursive_wrapper中第二次“打破继承周期”,它可以被删除。此外,// wo = one("sadfasdfas");也可以取消注解并按预期工作。

相关问题