任何访客都不使用会员功能

时间:2016-10-07 08:23:23

标签: c++ c++11 design-patterns visitor

我已经实施了一个简单的any类和一个合适的visitor类。这在功能级别上非常有用。但是当我尝试将访问者用作类中的成员时,会找到已注册的成员函数,但是没有输入。

这是一种我不理解的奇怪行为 我用gcc 5和6试了一下。
您可以在下面找到我的代码并在线here

程序应该增加一个整数值。

#include <iostream>
#include <functional>
#include <typeindex>
#include <unordered_map>

// simple any class
struct any {
    ~any() { if(val) { deleter_(val); } }
    template < class T >
    any(const T &v)
        : val(new T(v))
        , deleter_(&destroy<T>)
        , indexer_(&index<T>)
    {}

    typedef void (*deleter)(void*);
    typedef std::type_index (*indexer)();

    template <typename T>
    static void destroy(void *p) { delete (T*)p; }
    template < class T >
    static std::type_index index() { return std::type_index(typeid(T)); }

    template < class T >
    T& as() { return *static_cast<T*>(val); }

    std::type_index type_index() const { return indexer_(); }

    void *val = nullptr;
    deleter deleter_ = nullptr;
    indexer indexer_ = nullptr;

};

struct any_visitor {
    using function = std::function<void(any&)>;

    template <typename T>
    void register_visitor(const std::function<void(T&)> &f) {
        fs.insert(std::make_pair(
          std::type_index(typeid(T)),
          function([&f](any & x) {
            f(x.as<T>());
          })
        ));
    }

    void visit(any & x) {
        auto it = fs.find(x.type_index());
        if (it != fs.end()) {
            it->second(x);
        }
    }

    std::unordered_map<std::type_index, function> fs;
};

struct processor  {
    // visitor as class member
    any_visitor visitor;

    processor() {
        // register member function
        visitor.register_visitor<int>([this](int &i) { this->process(i); });
    }

    void apply(any &a) { visitor.visit(a); }

    void process(int &val) { ++val; }
};

int main()
{
    any ai = 7;
    any aii = 10;

    // visitor inside a function
    any_visitor visitor;
    visitor.register_visitor<int>([](int &val) {
        ++val;
    });
    // increment works
    std::cout << "function before: " << aii.as<int>() << "\n";
    visitor.visit(aii);
    std::cout << "function after: " << aii.as<int>() << "\n";

    // increment doesn't work
    std::cout << "class before: " << ai.as<int>() << "\n";
    processor p;
    p.apply(ai);
    std::cout << "class after: " << ai.as<int>() << "\n";

    return 0;
}

1 个答案:

答案 0 :(得分:0)

您正在存储对临时的引用,其中包含所有未定义的行为 register_visitor中的lambda函数需要按值捕获f