如何在 C++ 中实现基本的 Variant(以及 Variant 上的访问者)模板?

发布于 2024-08-18 21:29:54 字数 517 浏览 4 评论 0原文

我尝试阅读:

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);

谢谢!

I have tried reading:

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"

but still don't understand how variants are implemented. Can anyone paste a short example of how to define something like:

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


Variant<Type1, Type2> v;

v.somethingToSetupType1 ...;

somethingToTrigger process(Type1);

v.somethingToSetupType2 ...;

somethingToTrigger process(Type2);

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不忘初心 2024-08-25 21:29:54

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

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 向量 使该方法不仅适用于两种不同类型。

最后,你可以写这样的东西:

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

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

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

If i had to define a variant object, i'd probably start with the following :

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);
}

then use MPL vectors to make the approach work for more than just two different types.

In the end, you could write something like this :

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

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

NB : there is no chance this code compiles, but this describes the ideas i'd use.

拒绝两难 2024-08-25 21:29:54

认为您是在问如何使用变体,而不是如何实现它们。您可能需要查看有关变体的 Boost 文档;这比查看头文件更有帮助。

那么你的例子可能看起来像这样:

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);

I think you are asking how to use variants, not how to implement them. You may want to look at the boost documentation on variants; this will be much more helpful than looking at the header file.

Then your example might look something like this:

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文