// @generated from adl module test18
#ifndef TEST18_H
#define TEST18_H
#include <adl/adl.h>
#include <string>
#include <vector>

namespace ADL {
namespace test18 {

struct X1;

struct X2;

struct Y1;

struct Y2;

class X1
{
public:
    X1();
    static X1 mk_f1( const double & v );
    static X1 mk_f2( const Y1 & v );
    
    X1( const X1 & );
    ~X1();
    X1 & operator=( const X1 & );
    
    enum DiscType
    {
        F1,
        F2
    };
    
    DiscType d() const;
    
    template<class Visitor>
    void visit(Visitor vis) const
    {
        switch (d())
        {
        case F1: { vis.f1(f1()); break; }
        case F2: { vis.f2(f2()); break; }
        }
    }
    
    bool is_f1() const { return d_ == F1; };
    bool is_f2() const { return d_ == F2; };
    
    double & f1() const;
    Y1 & f2() const;
    
    const double & set_f1(const double & );
    const Y1 & set_f2(const Y1 & );
    
private:
    X1( DiscType d, void * v);
    
    DiscType d_;
    void *p_;
    
    static void free( DiscType d, void *v );
    static void *copy( DiscType d, void *v );
};

bool operator<( const X1 &a, const X1 &b );
bool operator==( const X1 &a, const X1 &b );

inline X1::DiscType X1::d() const
{
    return d_;
}

inline double & X1::f1() const
{
    if( d_ == F1 )
    {
        return *(double *)p_;
    }
    throw invalid_union_access();
}

inline Y1 & X1::f2() const
{
    if( d_ == F2 )
    {
        return *(Y1 *)p_;
    }
    throw invalid_union_access();
}

struct X2
{
    X2();
    
    X2(
        const double & f1,
        const std::vector<Y2>  & f2
        );
    
    double f1;
    std::vector<Y2>  f2;
};

bool operator<( const X2 &a, const X2 &b );
bool operator==( const X2 &a, const X2 &b );

class Y1
{
public:
    Y1();
    static Y1 mk_f1( const std::string & v );
    static Y1 mk_f2( const X1 & v );
    
    Y1( const Y1 & );
    ~Y1();
    Y1 & operator=( const Y1 & );
    
    enum DiscType
    {
        F1,
        F2
    };
    
    DiscType d() const;
    
    template<class Visitor>
    void visit(Visitor vis) const
    {
        switch (d())
        {
        case F1: { vis.f1(f1()); break; }
        case F2: { vis.f2(f2()); break; }
        }
    }
    
    bool is_f1() const { return d_ == F1; };
    bool is_f2() const { return d_ == F2; };
    
    std::string & f1() const;
    X1 & f2() const;
    
    const std::string & set_f1(const std::string & );
    const X1 & set_f2(const X1 & );
    
private:
    Y1( DiscType d, void * v);
    
    DiscType d_;
    void *p_;
    
    static void free( DiscType d, void *v );
    static void *copy( DiscType d, void *v );
};

bool operator<( const Y1 &a, const Y1 &b );
bool operator==( const Y1 &a, const Y1 &b );

inline Y1::DiscType Y1::d() const
{
    return d_;
}

inline std::string & Y1::f1() const
{
    if( d_ == F1 )
    {
        return *(std::string *)p_;
    }
    throw invalid_union_access();
}

inline X1 & Y1::f2() const
{
    if( d_ == F2 )
    {
        return *(X1 *)p_;
    }
    throw invalid_union_access();
}

struct Y2
{
    Y2();
    
    Y2(
        const std::string & f1,
        const std::vector<X2>  & f2
        );
    
    std::string f1;
    std::vector<X2>  f2;
};

bool operator<( const Y2 &a, const Y2 &b );
bool operator==( const Y2 &a, const Y2 &b );

}}; // ADL::test18

namespace ADL {

template <>
struct Serialisable<ADL::test18::X1>
{
    static Serialiser<ADL::test18::X1>::Ptr serialiser(const SerialiserFlags &);
};

template <>
struct Serialisable<ADL::test18::X2>
{
    static Serialiser<ADL::test18::X2>::Ptr serialiser(const SerialiserFlags &);
};

template <>
struct Serialisable<ADL::test18::Y1>
{
    static Serialiser<ADL::test18::Y1>::Ptr serialiser(const SerialiserFlags &);
};

template <>
struct Serialisable<ADL::test18::Y2>
{
    static Serialiser<ADL::test18::Y2>::Ptr serialiser(const SerialiserFlags &);
};

}; // ADL
#endif // TEST18_H
