2016-05-11 2 views
0

Я застрял :). У меня двухуровневая иерархия, каждый уровень имеет дочерние узлы. Цель состоит в том, чтобы использовать эту структуру для заполнения дерева gui. Я пытаюсь получить доступ к дочерним узлам вариантов элементов в общем виде. Следующий код не компилируется, используя vs2013. Я по достоинству оценит руку помощи и/или сообщит о конструктивных изменениях.boost :: variant - получить векторную характеристику членов

#include "stdafx.h" 
#include <memory> 
#include <string> 
#include <vector> 
#include <boost/variant.hpp> 

class base {}; 

class A : public base 
{ 
public: 
    std::vector<std::shared_ptr<base>> & lst(){ return _lst; } 
private: 
    std::vector<std::shared_ptr<base>> _lst; 
}; 

class B : public base 
{ 
public: 
    std::vector<std::shared_ptr<A>>& lst() { return _lst; } 
private: 
    std::vector<std::shared_ptr<A>> _lst; 
}; 

using bstvar = boost::variant<A, B>; 

class lstVisitor : public boost::static_visitor<> 
{ 
public: 
    template <typename T> std::vector<std::shared_ptr<base>>& operator() (T& t) const 
    { 
     return t.lst(); 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    bstvar test; 
    auto& lst= boost::apply_visitor(lstVisitor{}, test); 

    return 0; 
} 

ответ

0

Ваш посетитель имеет неявный тип возвращаемого void (шаблон аргумент отсутствует).

Вот пользуясь возможностью, чтобы удалить базовый класс, как он больше не нужен в большинстве C++ 11 кодовых баз:

Live On Coliru

#include <memory> 
#include <string> 
#include <vector> 
#include <boost/variant.hpp> 

class base {}; 

using base_vec = std::vector<std::shared_ptr<base> >; 

class A : public base { 
    public: 
    base_vec &lst() { return _lst; } 

    private: 
    base_vec _lst; 
}; 

class B : public base { 
    public: 
    base_vec &lst() { return _lst; } 

    private: 
    base_vec _lst; 
}; 

using bstvar = boost::variant<A, B>; 

struct lstVisitor { 
    using result_type = base_vec&; 
    template <typename T> result_type operator()(T &t) const { return t.lst(); } 
}; 

int main(int argc, char *argv[]) { 
    bstvar test { B{} }; 
    base_vec& lst = boost::apply_visitor(lstVisitor{}, test); 

    return 0; 
} 
+0

Большое спасибо! Вопрос, связанный с вашим комментарием: вы изменили возвращаемый параграф lst() на std :: vector > Класс B в примере имеет этот список, возвращающий векторы общих указателей на A. Я не вижу как я могу определить тип элементов в контейнере, если возвращает указатель на базовый класс. –

+0

Huh. 'operator()' явно уже возвращает это. Если вы настаиваете, вы можете конвертировать и возвращать копию ...: [demo] (http://coliru.stacked-crooked.com/a/2611392cee514d8e). К настоящему моменту я думаю, что вам нужно решить: для чего вам нужен статический полиморфизм и зачем вам нужен динамический полиморфизм. – sehe

+0

Последнее не имеет ничего общего с вариантом: см. ['Dynamic_cast'] (http://en.cppreference.com/w/cpp/language/dynamic_cast) и [' dynamic_pointer_cast'] (http: //en.cppreference. ком/ж/CPP/память/shared_ptr/pointer_cast). Кроме того, если вам нужны разные типы возврата, это означает, что у вас не может быть одного посетителя. Вы можете, конечно, вернуться ... еще один вариант (ухо): ** [так нравится] (http://coliru.stacked-crooked.com/a/5e87a1b585a59fab) **, но это похоже на достаточно большой [запах кода] (https://en.wikipedia.org/wiki/Code_smell) для меня. – sehe

Смежные вопросы