#define enum_( enum_name, base_type, ... )

        enum_name             : base_type { __VA_ARGS__ };

class   ENUM_ ## enum_name    : public  ENUM< ENUM_ ## enum_name, enum_name, base_type > {

using   enum_t = enum_name;     using   base_t = base_type;

public: CRE                     ENUM_ ## enum_name() { header( #__VA_ARGS__ );


#define enum_begin( N, T, ... ) enum _____ enum_( N, T, __VA_ARGS__ )

#define enum_class( N, T, ... ) enum class enum_( N, T, __VA_ARGS__ )


#define enum_value( label )     values[ #label ] = static_cast< base_t >( enum_t::label );


#define enum_end                footer(); } };


#define enum_ex( enum_name )    ENUM_ ## enum_name::get()


template< class enum_class, class enum_type, class base_type >

class                           ENUM : public SINGLETON< enum_class >

{

protected:

    void                        header( const i8* ptr )

    {

        while( *ptr )

        {

            i8  label[ 256 ];

            uu  i;

            for( i = 0; is_name( ptr[ i ] ); ++i )

                label[ i ] = ptr[ i ];

            label[ i ] = 0;

            for( ; ptr[ i ] && ptr[ i ] != ','; ++i );

            list.emplace_back( label );

            ptr += i;

            while( *ptr && *ptr < '0' ) ptr++;

        }

    }


    void                        footer()

    {

        base_type value = base_type();

        for( const oo& label : list )

        {

            oo  it = values.find( label );

            if( it != values.end() )

                value = it->second;

            labels[ value ] = label;

            values[ label ] = value++;

        }

    }


public:

    using   value_to_label =    std::map< base_type, std::string >;

    using   label_to_value =    std::map< std::string, base_type >;


    std::vector< std::string >  list;    

    value_to_label              labels;

    label_to_value              values;


    ENUM_ORDER                  order       = ENUM_ORDER::in;

    integralexpr                expression  = integralexpr::unsigned_decimal;


    template< class T >

    auto                        to_string( const T value )                      // do not const

    {

        return  labels[ static_cast< base_type >( value ) ];

    }


    auto                        to_const( const std::string& label )            // do not const

    {

        return  values[ label ];

    }


friend  std::ostream&           operator<<( std::ostream& os, enum_class& p )   // do not const

    {

        switch( p.order )

        {

        case    ENUM_ORDER::in:

            for( const oo& label : p.list )

                os << ::to_string( p.values[ label ], p.expression ) << ' ' << label << endl;

            break;

        case    ENUM_ORDER::label:

            for( const oo& item : p.values )

                os << ::to_string( item.second, p.expression ) << ' ' << item.first << endl;

            break;

        case    ENUM_ORDER::value:

            for( const oo& item : p.labels )

                os << ::to_string( item.first, p.expression ) << ' ' << item.second << endl;

            break;

        }

        return  os;

    }

};


앞에 #define 매크로들이 어떻게 돌아가는건지 80자 이내로 서술하시오.