Cómo implementar una variante básica (y un visitante en la variante) de plantillas de C ++?

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

Pregunta

lectura

He tratado:

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"

pero aún no entienden cómo se implementan las variantes. ¿Alguien puede pegar un pequeño ejemplo de cómo definir algo como:

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


Variant<Type1, Type2> v;

v.somethingToSetupType1 ...;

somethingToTrigger process(Type1);

v.somethingToSetupType2 ...;

somethingToTrigger process(Type2);

Gracias!

¿Fue útil?

Solución

Si tuviera que definir un objeto variante, probablemente comenzar con el siguiente:

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

a continuación, utilizar MPL vectores para hacer que el enfoque para algo más que dos tipos diferentes.

Al final, se podría escribir algo como esto:

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

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

Nota:. No hay ninguna posibilidad de que este código se compila, pero esto describe las ideas que haría uso

Otros consejos

pensar usted está pidiendo la forma de uso variantes, no la forma de implemento ellos. Es posible que desee ver en la href="http://www.boost.org/doc/libs/1_41_0/doc/html/variant.html" rel="nofollow noreferrer"> documentación impulso ; esto será mucho más útil que mirar el archivo de cabecera.

A continuación, el ejemplo podría ser algo como esto:

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