2016-10-07 5 views
0

간단한 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; 
} 

답변

0

당신은 정의되지 않은 동작을 수반하는 임시 참조를 저장하고 있습니다.
register_visitor의 람다 함수는 값으로 f을 캡처해야합니다.

+0

아야! 간단했다. A는 거의 모든 곳에서 보였지만 시도하지 않은 시도 중 하나였습니다. 고마워요! – zussel

관련 문제