Вызов функции на boost:: option независимо от типа?

У меня есть класс, который имеет шаблон:

 template<class T = int> class slider;

Класс имеет void Process(void) метод, так что, я думаю, он должен вызываться независимо от типа, возвращаемое значение равно void и в нем нет параметров.

На данный момент у меня есть этот код для вызова процесса каждый кадр в моем приложении:

//class menu:
typedef boost::variant<std::shared_ptr<slider<int>>,std::shared_ptr<slider<float>>,std::shared_ptr<slider<double>>,std::shared_ptr<slider<char>>> slider_type;
std::map<std::string,slider_type> Sliders;
//buttons ... etc ...
void Process()
{
    if(!Sliders.empty())
    {
        for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
        {
            switch(i->second.which())
            {
                case 0://slider<int>
                {
                    boost::get<std::shared_ptr<slider<int>>>(i->second)->Process();
                    break;
                }
                case 1://slider<float>
                {
                    boost::get<std::shared_ptr<slider<float>>>(i->second)->Process();
                    break;
                }
                //.....
            }
        }
    }
}

Можно ли выполнить функции Process(), как в следующем примере?

    for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
    {
        switch(i->second.which())
        {
            boost::get<???Any???>(i->second)->Process();
        }
    }

Если да, то как?

4 ответа

Что бы могла вернуть такая функция? Вы не можете изменить тип функции во время выполнения. И смысл варианта в том, что его содержимое определяется во время выполнения.

Единственное, что он может вернуть, это boost::any, Который на самом деле просто обменивает один вид неизвестного на другой (неизвестно, с которым гораздо сложнее иметь дело, когда вы не знаете, что в нем содержится, учтите). Но если вы хотите увидеть такого посетителя:

struct convert_to_any : public boost::static_visitor<boost::any>
{
  template<typename T> boost::any operator() (const T& t) {return t;}
};

использование apply_visitor на этом, и вы получите any назад. Хотя я не понимаю, как это полезно.


В любом случае, если вы используете get на variantВы почти наверняка делаете неправильные вещи. Правильный способ доступа к элементам варианта - с посетителем, а не с get,

В вашем случае посетитель должен быть простым:

struct ProcessVisitor : public boost::static_visitor<>
{
  template<typename T> void operator() (const T& t) const {t->Process();}
};

Просто используйте apply_visitor на что. Если вариант содержит тип, который можно использовать с operator-> и возвращаемое значение этой функции может иметь Process призвал его, тогда будет.

(Непроверенный код!)

struct CallProcess : static_visitor<>
{
  template <class T>
  void operator()(const T &t) const
  {
    t->Process();
  }
};

for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
  boost::apply_visitor(CallProcess(), i->second);
}

Нет, совсем нет. Вы должны посетить и разобраться с делом любого типа. Это гораздо лучше сделать с посетителем, чем ваш хакерский ключ.

Это невозможно, потому что boost::variant не может знать, что все типы в variant есть что-то общее. Фактически, поскольку компилятор генерирует отдельный класс для каждой используемой специализации шаблона, адрес Process() Функция, которая должна быть использована, отличается для каждого типа в boost::variant, Чтобы обойти это вы можете отказаться variant и использовать виртуальные функции и полиморфные классы, разделяющие общий базовый класс.

Другие вопросы по тегам