#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 ) );; } }; } /* namespace core */