【问题标题】:How to implement a basic Variant (& a visitor on the Variant) template in C++?如何在 C++ 中实现基本的 Variant(以及 Variant 上的访问者)模板?
【发布时间】:2010-01-25 10:29:23
【问题描述】:

我试过阅读:

http://www.boost.org/doc/libs/1_41_0/boost/variant.hpp


http://www.codeproject.com/KB/cpp/TTLTyplist.aspx


and chapter 3 of "Modern C++ Design"

但仍然不明白变体是如何实现的。任何人都可以粘贴一个简短的例子来说明如何定义类似的东西:

class Foo {
  void process(Type1) { ... };
  void process(Type2) { ... };
};


Variant<Type1, Type2> v;

v.somethingToSetupType1 ...;

somethingToTrigger process(Type1);

v.somethingToSetupType2 ...;

somethingToTrigger process(Type2);

谢谢!

【问题讨论】:

  • 你是问如何实现变体,或者如何使用boost的实现?
  • 很明显他想知道如何实现变体。
  • 我想知道如何实现;不是如何使用变体。

标签: c++ templates variant typelist


【解决方案1】:

如果我必须定义一个变体对象,我可能会从以下开始:

template<typename Type1, typename Type2>
class VariantVisitor;

template<typename Type1, typename Type2>
class Variant
{
public:
   friend class VariantVisitor<Type1, Type2>;
   Variant();
   Variant(Type1);
   Variant(Type2);
   // + appropriate operators =
   ~Variant(); // deal with memory management

private:
    int type; // 0 for invalid data, 1 for Type1, 2 for Type2
    void* data;
};

template<typename Visitor, typename Type1, typename Type2>
class VariantVisitor 
{
   private:
     Visitor _customVisitor;
   public:
   void doVisit(Variant<Type1, Type2>& v)
   {
      if( v.type == 1 )
      {
          _customVisitor( *(Type1*)(v.data));
      }
      else if( v.type == 2 )
      {
          _customVisitor( *(Type2*)(v.data));
      }
      else
      {
         // deal with empty variant
      }
   }
};
template<typename Visitor, typename Type1, typename Type2>
void visit( Visitor visitor, Variant<Type1, Type2> v )
{
  VariantVisitor<Visitor, Type1, Type2>(visitor).doVisit(v);
}

然后使用MPL vectors 使该方法不仅适用于两种不同的类型。

最后,你可以这样写:

Variant<Type1, Type2> v;
class MyVisitor
{
  public:
  operator()(Type1);
  operator()(Type2);
};

MyVisitor visitor;
v = Type1();
visit(visitor, v);
v = Type2();
visit(visitor, v);

注意:这段代码不可能编译,但这描述了我会使用的想法。

【讨论】:

  • 不过,我怀疑它是不是类似于 Boost.Variant。例如,sizeof(variant) 是否依赖于最大的类型——这表明这些值不存储为void*? - 不幸的是,源代码对我来说太长太复杂了(可能需要为实现目标的每一步都与编译器抗争,所以我很感激我可以在需要时使用其他人的工作:))
  • 我完全同意。我永远不会使用个人版本的变体。 Boost.Variant 工作正常,我真的不需要知道如何。我只是在解释它如何完成。
【解决方案2】:

认为您问的是如何使用变体,而不是如何实现它们。你可能想看看boost documentation on variants;这将比查看头文件更有帮助。

那么您的示例可能如下所示:

class v_visitor : public boost::static_visitor
{
public:
   void operator()(Type1 &t) const {...}
   void operator()(Type2 &t) const {...}
};

v = Type1(...);
boost::apply_visitor(v_visitor(), v);

【讨论】:

    猜你喜欢
    • 2011-04-06
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 2022-07-08
    相关资源
    最近更新 更多