0

我有一个有模板的类:

 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

4 回答 4

5

这样的函数会返回什么?您不能在运行时更改函数的类型。变体的重点是它的内容是在运行时确定的。

它唯一可以返回的是一个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在 a 上使用variant,你几乎肯定做错了事。访问变体元素的正确方法是使用访问者,而不是使用get.

在您的情况下,访问者应该很简单:

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

就用apply_visitor那个。如果变体包含可以使用的类型,operator->并且该函数的返回值可以Process调用它,那么它会调用。

于 2013-05-17T02:40:34.563 回答
4

(未经测试的代码!)

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);
}
于 2013-05-17T06:38:43.727 回答
2

一点都不。您必须访问并处理每种类型的案例。与访问者相比,这比你的 switch hack 要好得多。

于 2013-05-17T01:37:08.927 回答
1

这是不可能的,因为boost::variant无法知道 中的所有类型variant都有任何共同点。事实上,由于编译器会为使用的每个模板特化生成一个不同的类,Process()因此需要使用的函数地址对于boost::variant. 为了解决这个问题,您可以放弃variant并使用共享公共基类的虚函数和多态类。

于 2013-05-17T01:57:39.847 回答