كيفية تنفيذ نموذج البديل الأساسي (والزائر على البديل) في C ++؟

StackOverflow https://stackoverflow.com/questions/2131604

سؤال

لقد حاولت القراءة:

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

شكرًا!

هل كانت مفيدة؟

المحلول

إذا اضطررت إلى تحديد كائن متغير ، فربما أبدأ بما يلي:

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

NB: لا توجد فرصة لتجميع هذا الرمز ، ولكن هذا يصف الأفكار التي أستخدمها.

نصائح أخرى

أنا فكر في أنت تسأل كيف استعمال المتغيرات ، وليس كيف ينفذ معهم. قد ترغب في إلقاء نظرة على زيادة الوثائق على المتغيرات; ؛ سيكون هذا أكثر فائدة من النظر إلى ملف الرأس.

ثم قد يبدو مثالك مثل هذا:

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);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top