Skip to content
Snippets Groups Projects
ObjectFactory.h 5.78 KiB
Newer Older
  • Learn to ignore specific revisions
  • #pragma once
    
    #include <ext/variant>
    #include <object/Object.h>
    #include <object/AnyObject.h>
    
    namespace object {
    
    template < class Type >
    class ObjectFactoryImpl {
    public:
    	/**
    	 * \brief
    	 * Specialisation of the make method for objects that are not from the object hierarchy of Algorithms library
    	 */
    	static Object construct ( Type && data ) {
    		return ObjectFactoryImpl < object::AnyObject < typename std::decay < Type >::type > >::construct ( object::AnyObject < typename std::decay < Type >::type > ( std::forward < Type > ( data ) ) );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < Object > {
    public:
    	static Object construct ( Object && object ) {
    		return std::move ( object );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < const Object & > {
    public:
    	static Object construct ( const Object & object ) {
    		return object;
    	}
    };
    
    template < >
    class ObjectFactoryImpl < Object & > {
    public:
    	static Object construct ( Object & object ) {
    		return object;
    	}
    };
    
    template < >
    class ObjectFactoryImpl < const char * const & > {
    public:
    	static Object construct ( const char * const string ) {
    		return ObjectFactoryImpl < std::string >::construct ( std::string ( string ) );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < char * const & > {
    public:
    	static Object construct ( char * const string ) {
    		return ObjectFactoryImpl < std::string >::construct ( std::string ( string ) );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < const char * & > {
    public:
    	static Object construct ( const char * const string ) {
    		return ObjectFactoryImpl < std::string >::construct ( std::string ( string ) );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < char * & > {
    public:
    	static Object construct ( char * const string ) {
    		return ObjectFactoryImpl < std::string >::construct ( std::string ( string ) );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < const char * const > {
    public:
    	static Object construct ( const char * const string ) {
    		return ObjectFactoryImpl < std::string >::construct ( std::string ( string ) );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < char * const > {
    public:
    	static Object construct ( char * const string ) {
    		return ObjectFactoryImpl < std::string >::construct ( std::string ( string ) );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < const char * > {
    public:
    	static Object construct ( const char * string ) {
    		return ObjectFactoryImpl < std::string >::construct ( std::string ( string ) );
    	}
    };
    
    template < >
    class ObjectFactoryImpl < char * > {
    public:
    	static Object construct ( char * string ) {
    		return ObjectFactoryImpl < std::string >::construct ( std::string ( string ) );
    	}
    };
    
    namespace details {
    	/**
    	 * \brief
    	 * Helper method to detect variant content and call make method on the object from inside of the variant.
    	 */
    	template < class Variant >
    	static Object processVariant ( Variant && data ) {
    		auto visitor = [] < class Type > ( Type && element ) {
    			return ObjectFactoryImpl < Type >::construct ( std::forward < Type > ( element ) );
    		};
    
    		return ext::visit ( visitor, std::forward < Variant > ( data ) );
    	}
    }
    
    /**
     * \brief
     * Specialisation of the make method for variants.
     *
     * \details
     * The resulting object is not constructed from the variant itself but from the value stored inside. If the value stored inside the variant is variant again, the process is repeated.
     */
    template < class ... Types >
    class ObjectFactoryImpl < ext::variant < Types ... > > {
    public:
    	static Object construct ( ext::variant < Types ... > && data ) {
    		return details::processVariant ( std::move ( data ) );
    	}
    };
    
    /**
     * \brief
     * Specialisation of the make method for variants.
     *
     * \details
     * The resulting object is not constructed from the variant itself but from the value stored inside. If the value stored inside the variant is variant again, the process is repeated.
     */
    template < class ... Types >
    class ObjectFactoryImpl < const ext::variant < Types ... > & > {
    public:
    	static Object construct ( const ext::variant < Types ... > & data ) {
    		return details::processVariant ( data );
    	}
    };
    
    /**
     * \brief
     * Specialisation of the make method for variants.
     *
     * \details
     * The resulting object is not constructed from the variant itself but from the value stored inside. If the value stored inside the variant is variant again, the process is repeated.
     */
    template < class ... Types >
    class ObjectFactoryImpl < ext::variant < Types ... > & > {
    public:
    	static Object construct ( ext::variant < Types ... > & data ) {
    		return details::processVariant ( data );
    	}
    };
    
    /**
     * Constructor that wraps an object given by a constant reference. Uses clone of the parameter internally.
     */
    template < class Type >
    class ObjectFactoryImpl < const AnyObject < Type > & > {
    public:
    	static Object construct ( const AnyObject < Type > & data ) {
    		return Object ( data.clone ( ) );
    	}
    };
    
    /**
     * Constructor that wraps an object given by a reference. Uses clone of the parameter internally.
     */
    template < class Type >
    class ObjectFactoryImpl < AnyObject < Type > & > {
    public:
    	static Object construct ( AnyObject < Type > & data ) {
    		return Object ( data.clone ( ) );
    	}
    };
    
    /**
     * Constructor that wraps an object given by an r-value reference. Uses clone of the parameter internally.
     */
    template < class Type >
    class ObjectFactoryImpl < AnyObject < Type > > {
    public:
    	static Object construct ( AnyObject < Type > && data ) {
    		return Object ( std::move ( data ).clone ( ) );
    	}
    };
    
    template < class Type = Object >
    class ObjectFactory {
    public:
    	template < class Param >
    	static Type construct ( Param && param ) {
    		return Type ( std::forward < Param > ( param ) );;
    	}
    };
    
    template < >
    class ObjectFactory < Object > {
    public:
    	template < class Param >
    	static Object construct ( Param && param ) {
    
    		return ObjectFactoryImpl < typename ext::array_to_ptr < Param >::type >::construct ( std::forward < Param > ( param ) );;