【问题标题】:Adding debugging facilities to boost variant visitor添加调试工具以提升变体访问者
【发布时间】:2018-07-20 06:20:35
【问题描述】:

我在整个项目中都使用boost-variant,我认为它是boost 中最有用和最通用的工具之一。

但如果涉及递归嵌套变体的访问者模式的复杂使用,调试有时会很麻烦。

因此我决定实现一个可重复使用的DebugVisitor,它可能会添加到我现有的访问者中。如果出现缺陷,它应该很容易添加/删除给我现有的访问者。

易于移除意味着它应该可以添加到任何现有的访问者类中,而不是修改使用访问者实例的地方。

我试图找到一个符合我要求的解决方案。以下代码编译,但不幸的是它没有打印消息。

有人知道为什么吗?

#include <iostream>
#include <boost/variant.hpp>
#include <functional>

template<typename V> // V must have the boost::static_visitor Interface
struct DebugVisitor : public V {
    template<typename U>
    typename V::result_type operator()(const U& u) const {
        std::cout << "Visiting Type:" << typeid(U).name() << " with Visitor: " << typeid(V).name() << std::endl;
        return V::operator()(u);
    }
};


struct AddVisitor : public DebugVisitor<boost::static_visitor<boost::variant<int, double>>> {
    template<typename U>
    result_type operator()(const U& u) const {
        return u + 1.;
    }
};

int main(int, char**) {
    boost::variant<double, int> number{ 3.2 };

    AddVisitor d;
    auto incr=number.apply_visitor(d);
    if (auto dValue = boost::get<double>(incr)) {
        std::cout << "Increment: " << dValue << std::endl;
    }
    return 0;
}

【问题讨论】:

  • 你的第一个例子使用T,但没有定义它
  • @Caleth:谢谢。我删除了旧解决方案。

标签: c++ crtp boost-variant visitor-pattern


【解决方案1】:

看不到调试输出的原因是AddVisitor::operator() 没有调用DebugVisitor::operator()。如果是这样,您将在尝试解析boost::static_visitor&lt;&gt;::operator() 时出错,不存在

选项 1。

只要有条件地编译AddVisitor定义中的调试

struct AddVisitor : public boost::static_visitor<boost::variant<int, double>> {
    template<typename U>
    result_type operator()(const U& u) const {
#ifdef DEBUG
        std::cout << "Visiting Type:" << typeid(U).name() << " with Visitor: " << typeid(AddVisitor).name() << std::endl;
#endif
        return u + 1.;
    }
};

选项 2。

有条件地定义符号AddVisitorDebugVisitor包裹

template<typename V> // V must have the boost::static_visitor Interface
struct DebugVisitor : public V {
    template<typename U>
    typename V::result_type operator()(const U& u) const {
        std::cout << "Visiting Type:" << typeid(U).name() << " with Visitor: " << typeid(V).name() << std::endl;
        return V::operator()(u);
    }
};

struct AddVisitorBase : public boost::static_visitor<boost::variant<int, double>> {
    template<typename U>
    result_type operator()(const U& u) const {
        return u + 1.;
    }
};

#ifdef DEBUG
using AddVisitor = DebugVisitor<AddVisitorBase>;
#else
using AddVisitor = AddVisitorBase;
#endif

选项 3。

一对 CRTP 碱基

template<typename V> // V must have the boost::static_visitor Interface
struct DebugVisitor : public V {
    template<typename U>
    typename V::result_type operator()(const U& u) const {
        std::cout << "Visiting Type:" << typeid(U).name() << " with Visitor: " << typeid(V).name() << std::endl;
        return V::call(u);
    }
};

template<typename V> // V must have the boost::static_visitor Interface
struct NotDebugVisitor : public V {
    template<typename U>
    typename V::result_type operator()(const U& u) const {
        return V::call(u);
    }
};

struct AddVisitor : public boost::static_visitor<boost::variant<int, double>>, public 
#ifdef DEBUG
DebugVisitor<AddVisitor>
#else
NotDebugVisitor<AddVisitor>
#endif
{
    template<typename U>
    result_type call(const U& u) const {
        return u + 1.;
    }
};

【讨论】:

  • 感谢您的解决方案,但很遗憾它不符合我的要求。假设我在项目周围分散的地方使用 AddVisitor。现在,出了点问题,我想将调试工具添加到我所有的 AddVisitor 中。然后我必须在每个地方更换它。如果我能以某种方式将调试工具添加到 AddVisitor,那就太好了。
  • 不错。有什么方法可以避免出现 AddVisitorBase 和 AddVisitor?
  • 并非如此。您可以在命名空间中隐藏 AddVisitorBase
  • 不可能有像struct AddVisitor : public DebugVisitor&lt;AddVisitor&lt;boost::variant&lt;int, double&gt;&gt; 这样的解决方案?
  • 你仍然需要更改operator(),这样你就不会隐藏从DebugVisitor继承的那个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多