代码之家  ›  专栏  ›  技术社区  ›  Aleph0

添加调试工具以增强变量访问者

  •  0
  • Aleph0  · 技术社区  · 6 年前

    我在用 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;
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Caleth    6 年前

    您没有看到调试输出的原因是 AddVisitor::operator() 不打电话 DebugVisitor::operator() . 如果是这样,您在尝试解决时会遇到一个错误 boost::static_visitor<>::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。

    有条件地定义符号 添加访问者 被包裹着 DebugVisitor

    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.;
        }
    };
    
    推荐文章