text: /////////////////////////////////////////////////////////////////////////////////
  //
  // Aurora C++ Library
  // Copyright (c) 2012-2016 Jan Haller
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //    claim that you wrote the original software. If you use this software
  //    in a product, an acknowledgment in the product documentation would be
  //    appreciated but is not required.
  //
  // 2. Altered source versions must be plainly marked as such, and must not be
  //    misrepresented as being the original software.
  //
  // 3. This notice may not be removed or altered from any source distribution.
  //
  /////////////////////////////////////////////////////////////////////////////////
  
  /// @file
  /// @brief Class template aurora::Optional
  
  #ifndef AURORA_OPTIONAL_HPP
  #define AURORA_OPTIONAL_HPP
  
  #include <TGUI/extlibs/Aurora/Config.hpp>
  #include <TGUI/extlibs/Aurora/Tools/SafeBool.hpp>
  #include <TGUI/extlibs/Aurora/Tools/Swap.hpp>
  
  #include <type_traits> // std::aligned_storage
  #include <cassert>
  #include <new> // placement new (g++ non-conformance, not required by C++ standard)
  
  
  namespace aurora
  {
  
  /// @addtogroup Tools
  /// @{
  
  /// @relates Optional
  /// @brief Null literal for optional objects
  /// @details @c aurora::nullopt can be used to expressively refer to empty optionals. It is convertible to @ref aurora::Optional<T>
  ///  instances of any type T.
  /// @code
  /// aurora::Optional<MyClass> function()
  /// {
  ///     if (...)
  ///         return MyClass(...);
  ///     else
  ///         return aurora::nullopt;
  /// }
  /// @endcode
  const struct NulloptType {} nullopt;
  
  /// @relates Optional
  /// @brief Tag to construct optional objects in-place
  /// @details @c aurora::inplace is used in the <tt>Optional::Optional(InplaceType, Args&&... args)</tt> constructor.
  /// @see makeOptional()
  const struct InplaceType {} inplace;
  
  /// @brief Represents optional values.
  /// @details This class extends objects with an additional @a null state, which explicitly denotes the absence of a valid object.
  ///  There are many situations where an object can either carry a valid state or none, especially in function return values.
  ///  For example, let's assume we have a function @c find() that searches for a T object, but doesn't always find one.
  ///  C++ offers many ways to deal with this situation, but the usual ones come with certain drawbacks:
  ///  * <tt>T* find()</tt> -- the pointer must refer to a stored object (no temporary) or require dynamic allocation
  ///  * <tt>iterator find()</tt> + comparison with @c end() -- requires an underlying container and exposes implementation details
  ///  * <tt>bool has()</tt> + <tt>T find()</tt> -- requires two calls, thus two possibly expensive searches instead of one
  ///  * <tt>bool find(T& out)</tt> -- user must construct T up-front, requiring a default constructor, incurring useless initialization
  ///    and preventing const qualifier
  ///
  /// This class offers a new way:
  ///  * <tt>Optional<T> find()</tt>
  ///
  /// The syntax is very similar to a pointer, with dereferencing operators and conversion to bool contexts:
  /// @code
  /// aurora::Optional<T> opt = find();
  /// if (opt) // check if 'opt' has a value
  ///     use(*opt); // dereference 'opt' to access the T object
  /// @endcode
  ///
  /// You can even simplify this code further, using type inference and the little-known C++ feature of declarations inside if statements:
  /// @code
  /// if (auto opt = find())
  ///     use(*opt);
  /// @endcode
  ///
  /// This class can be used as an interim solution until <tt>std::optional</tt> becomes part of a C++ standard and is supported by all
  ///  major compilers. aurora::Optional uses a very similar (although slightly smaller) API.
  template <typename T>
  class Optional
  {
  	// ---------------------------------------------------------------------------------------------------------------------------
  	// Public member functions
  	public:
  		/// @brief Construct empty optional with default constructor
  		///
  		Optional()
  		: mFilled(false)
  		{
  		}
  
  		/// @brief Construct empty optional from @ref aurora::NulloptType "aurora::nullopt"
  		///
  		Optional(NulloptType)
  		: mFilled(false)
  		{
  		}
  
  #ifdef AURORA_HAS_VARIADIC_TEMPLATES
  
  		/// @brief Construct object in-place, forwarding arguments
  		///
  		template <typename... Args>
  		explicit Optional(InplaceType, Args&&... args)
  		: mFilled(false)
  		{
  			construct(std::forward<Args>(args)...);
  		}
  
  #endif // AURORA_HAS_VARIADIC_TEMPLATES
  
  		/// @brief Construct implicitly from T object (move or copy)
  		///
  		Optional(T object)
  		: mFilled(false)
  		{
  			construct(std::move(object));
  		}
  
  		/// @brief Copy constructor
  		///
  		Optional(const Optional& origin)
  		: mFilled(false)
  		{
  			if (origin.mFilled)
  				construct(origin.content());
  		}
  
  		/// @brief Move constructor
  		///
  		Optional(Optional&& source)
  		: mFilled(false)
  		{
  			if (source.mFilled)
  			{
  				construct(std::move(source.content()));
  				source.destroy();
  			}
  		}
  
  		/// @brief Assign from T object (move or copy)
  		///
  		Optional& operator= (T object)
  		{
  			Optional(std::move(object)).swap(*this);
  			return *this;
  		}
  
  		/// @brief Copy assignment operator
  		///
  		Optional& operator= (const Optional& origin)
  		{
  			Optional(origin).swap(*this);
  			return *this;
  		}
  
  		/// @brief Move assignment operator
  		///
  		Optional& operator= (Optional&& source)
  		{
  			Optional(std::move(source)).swap(*this);
  			return *this;
  		}
  
  		/// @brief Destructor
  		///
  		~Optional()
  		{
  			if (mFilled)
  				destroy();
  		}
  
  		/// @brief Swaps two optional objects.
  		///
  		void swap(Optional& other)
  		{
  			// TODO: Exception safety in 2nd and 3rd case
  
  			if (mFilled && other.mFilled)
  			{
  				adlSwap(content(), other.content());
  			}
  			else if (mFilled)
  			{
  				other.construct(std::move(content()));
  				this->destroy();
  			}
  			else if (other.mFilled)
  			{
  				this->construct(std::move(other.content()));
  				other.destroy();
  			}
  		}
  
  		/// @brief Returns the contained object.
  		/// @warning Dereferencing empty optionals yields undefined behavior.
  		T& operator* ()
  		{
  			return content();
  		}
  
  		/// @brief Returns the contained object (const overload).
  		/// @warning Dereferencing empty optionals yields undefined behavior.
  		const T& operator* () const
  		{
  			return content();
  		}
  
  		/// @brief Returns the contained object for member access.
  		/// @warning Dereferencing empty optionals yields undefined behavior.
  		T* operator-> ()
  		{
  			return &content();
  		}
  
  		/// @brief Returns the contained object for member access (const overload).
  		/// @warning Dereferencing empty optionals yields undefined behavior.
  		const T* operator-> () const
  		{
  			return &content();
  		}
  
  		/// @brief Check if the optional object contains a value.
  		///
  		operator SafeBool() const
  		{
  			return toSafeBool(mFilled);
  		}
  
  
  	// ---------------------------------------------------------------------------------------------------------------------------
  	// Private member functions
  	private:
  		T& content()
  		{
  			assert(mFilled);
  			return reinterpret_cast<T&>(mStorage);
  		}
  
  		const T& content() const
  		{
  			assert(mFilled);
  			return reinterpret_cast<const T&>(mStorage);
  		}
  
  #ifdef AURORA_HAS_VARIADIC_TEMPLATES
  
  		template <typename... Args>
  		void construct(Args&&... args)
  		{
  			// Exception safety: set mFilled only to true after successful construction
  
  			assert(!mFilled);
  			new (&content()) T(std::forward<Args>(args)...);
  			mFilled = true;
  		}
  
  #else
  
  		void construct(T& source)
  		{
  			assert(!mFilled);
  			new (&content()) T(std::move(source);
  			mFilled = true;
  		}
  
  #endif // AURORA_HAS_VARIADIC_TEMPLATES
  
  		void destroy()
  		{
  			assert(mFilled);
  			content().~T();
  			mFilled = false;
  		}
  
  	// ---------------------------------------------------------------------------------------------------------------------------
  	// Private variables
  	private:
  		typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type	mStorage;
  		bool																		mFilled;
  };
  
  /// @relates Optional
  /// @brief Swaps two optionals.
  template <typename T>
  void swap(Optional<T>& lhs, Optional<T>& rhs)
  {
  	lhs.swap(rhs);
  }
  
  #ifdef AURORA_HAS_VARIADIC_TEMPLATES
  
  /// @relates Optional
  /// @brief Emplaces an object directly inside the aurora::Optional object.
  /// @details Example:
  /// @code
  /// // These declarations are semantically equivalent (however different constructors can be called):
  /// aurora::Optional<MyClass> opt(aurora::inplace, arg1, arg2);
  /// auto opt = aurora::makeOptional<MyClass>(arg1, arg2); // may invoke move constructor
  /// aurora::Optional<MyClass> opt = MyClass(arg1, arg2); // may invoke move or copy constructor
  /// @endcode
  /// @param args Variable argument list, the single arguments are forwarded to T's constructor.
  /// @see InplaceType
  template <typename T, typename... Args>
  Optional<T> makeOptional(Args&&... args)
  {
  	return Optional<T>(inplace, std::forward<Args>(args)...);
  }
  
  #endif // AURORA_HAS_VARIADIC_TEMPLATES
  
  /// @relates Optional
  /// @brief Equality comparison
  /// @details Semantics: Returns true if both operands are empty, or if both are non-empty
  ///  and the expression <tt>*lhs == *rhs<tt> returns true.
  template <typename T>
  bool operator== (const Optional<T>& lhs, const Optional<T>& rhs)
  {
  	return !lhs && !rhs
  		|| lhs && rhs && *lhs == *rhs;
  }
  
  /// @relates Optional
  /// @brief Inequality comparison
  /// @see operator==(const Optional<T>& lhs, const Optional<T>& rhs)
  template <typename T>
  bool operator!= (const Optional<T>& lhs, const Optional<T>& rhs)
  {
  	return !(lhs == rhs);
  }
  
  /// @}
  
  } // namespace aurora
  
  #endif // AURORA_OPTIONAL_HPP
  