gpt4 book ai didi

c++ - 避免 boost::variant 访问者中的冗余代码

转载 作者:行者123 更新时间:2023-11-28 02:00:50 25 4
gpt4 key购买 nike

我遇到了以下问题:我有一些 boost::variant 访问者,它们都对特定类型做同样的事情,这里是 foo,所以方法

void operator()(const foo& ast)
{
//allways the same
}

在每个访问者中都是一样的。由于我不想在所有访问者中编写这个冗余方法,因此我试图避免向所有访问者添加一个实现此方法的公共(public)基类。问题方法递归调用访问者本身,如下所示:

void operator(const foo& ast)
{
for(auto&& item : ast.members)
{
boost::apply_visitor(*this, item);
}
}

并且因为所有其他与成员匹配的方法都没有在基类中实现,所以我得到一个编译器错误。现在我的问题是,如何摆脱冗余代码?

这是一个关于问题可能看起来的例子:

struct variant_one;
struct variant_two;
struct nil{};
typedef boost::variant<
boost::spirit::x3::forward_ast<variant_one>,
boost::spirit::x3::forward_ast<variant_two>,
nil
> example_variant;

struct variant_one {};
struct variant_two
{
std::vector<example_variant> members;
};


struct visitor_one : boost::static_visitor<void>
{
void operator()(const variant_one& ast)
{
std::cout << "visitor_one detected var_one" << std::endl;
}

//this is the redundant method
void operator()(const variant_two& ast)
{
std::cout << "visitor detected var_two, output members:" <<std::endl;
for(auto&& member : ast.members)
{
boost::apply_visitor(*this, member);
}
}
}

struct visitor_two : boost::static_visitor<void>
{

void operator()(const variant_one& ast)
{
std::cout << "visitor_one detected var_two" << std::endl;
}

//this is the redundant method
void operator()(const variant_two& ast)
{
std::cout << "visitor detected var_two, output members:" <<std::endl;
for(auto&& member : ast.members)
{
boost::apply_visitor(*this, member);
}
}
}

最佳答案

是这样的吗?

template<typename Derived>
struct VisitorBase {
void operator()(const foo& ast) {
for(auto&& item : ast.members) {
boost::apply_visitor(*static_cast<Derived*>(this), item);
}
}
};

struct VisitorA : VisitorBase<VisitorA> {
void operator()(const ItemType& item) {
// do stuff
}
};

或者如果访问者中使用的类型相同/事先已知并且虚函数没问题:

struct VisitorBase {
void operator()(const foo& ast) {
for(auto&& item : ast.members) {
boost::apply_visitor(*this, item);
}
}
virtual void operator()(const ItemTypeA&) = 0;
virtual void opetator()(const ItemTypeB&) = 0;
};

struct VisitorA : VisitorBase {
void operator()(const ItemTypeA& item) {
// do stuff
}
void operator()(const ItemTypeB& item) {
// do stuff
}
};

在第一个示例中,您可能希望确保不会意外地使用非派生类型实例化模板,例如:

static_assert(std::is_base_of<VisitorBase,Derived>::value, "Derived should be derived from VisitorBase");

这仍然会保留在模板参数中使用不同的 VisitorBase 派生类型实例化 VisitorBase 派生类型的可能性,从而导致未定义的行为。所以要小心。

关于c++ - 避免 boost::variant 访问者中的冗余代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39658620/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com