<commit_before>// Union.h - Copyright 2013-2016 <NAME>, All Rights Reserved
#pragma once

#include <limits>
#include "../Forwards/Reflection.h"
#include "../Math/Math.h"
#include "Nullable.h"

template <typename ... T>
struct Union final
{
	///////////////////////
	///   Inner Types   ///
private:

	/** Honestly if you need a Union of more than 255 types you're doing something wrong. */
	using Index = byte;

	/** Aliasis a type_sequence holding the types supported by this Union. */
	using Seq = stde::type_sequence<T...>;

	static_assert(sizeof...(T) <= std::numeric_limits<Index>::max(), "You have too many types in this Union.");

	////////////////////////
	///   Constructors   ///
public:

	Union() = default;
	Union(const Union& copy)
		: Union()
	{
		self = copy;
	}
	Union(Union&& move)
		: Union()
	{
		self = std::move(move);
	}
	~Union()
	{
		Nullify();
	}

	template <typename F, WHERE(!std::is_same<std::decay_t<F>, Union>::value)>
	Union(F&& value)
		: Union()
	{
		Set(std::forward<F>(value));
	}

	///////////////////
	///   Methods   ///
public:

	/** Returns whether this Union is currently holding a value. */
	FORCEINLINE bool HasValue() const
	{
		return _index.HasValue();
	}

	/** Returns the type of the currently held value.
	* NOTE: Returns 'null' if this Union is not currently holding a value. */
	const TypeInfo* GetCurrentType() const
	{
		if (_index.HasValue())
		{
			return Invoke<const TypeInfo*>([](const auto& a) { return &TypeOf(a); });
		}
		else
		{
			return nullptr;
		}
	}

	/** Destroys the currently held value. */
	void Nullify()
	{
		if (HasValue())
		{
			// Destroy the value
			Invoke([](auto& v) -> void
			{
				using F = std::decay_t<decltype(v)>;
				v.~F();
			});
			_index.Nullify();
		}
	}

	/** Returns the current value as a Variant. 
	* WARNING: This function will fail if this Union is not currently holding a value. */
	Variant Get();

	/** Returns the current value as an ImmutableVariant. 
	* WARNING: This function will fail if this Union is not currently holding a value. */
	ImmutableVariant Get() const;

	/** Sets the current value of this Union. */
	template <typename F>
	void Set(F&& value)
	{
		using DecayF = std::decay_t<F>;
		Index newIndex = IndexOf<DecayF>();

		// If we have a currently loaded value
		if (_index.HasValue())
		{
			// If the currently loaded value is of the same type as the new value
			if (_index.GetValue() == newIndex)
			{
				// Just assign directly
				Get<DecayF>() = std::forward<F>(value);
				return;
			}
			else
			{
				// Delete current value
				Nullify();
			}
		}

		_value.Emplace<DecayF>(std::forward<F>(value));
		_index = newIndex;
	}

	/** Gets the current value of this Union as the given type.
	* WARNING: This function will fail if this Variant is not currently holding a value of the given type. */
	template <typename F>
	F& Get()
	{
		assert(HasValue() && _index.GetValue() == IndexOf<F>());
		return *_value.template GetPointer<F>();
	}

	/** Gets the current value of this Union as the given type.
	* WARNING: This function will fail if this Variant is not currently holding a value of the given type. */
	template <typename F>
	const F& Get() const
	{
		assert(_index.HasValue() && _index.GetValue() == IndexOf<F>());
		return *_value.template GetPointer<F>();
	}

	/** Invokes the given function on the current value.
	* WARNING: If this Union is not holding a value, this function will fail. */
	template <typename R = void, typename Func>
	R Invoke(const Func& func)
	{
		using Invoker = R (void*, const Func&);	
		Invoker* funcs[] = { CreateInvoker<T, R, Func>()... };
		
		assert(HasValue());
		return funcs[_index.GetValue()](_value.GetPointer<void>(), func);
	}

	/** Invokes the given function on the current value.
	* WARNING: If this Union is not holding a value, this function will fail. */
	template <typename R = void, typename Func>
	R Invoke(const Func& func) const
	{
		using Invoker = R (const void*, const Func&);
		Invoker* funcs[] = { CreateInvoker<T, R, Func>()... };

		assert(HasValue());
		return funcs[_index.GetValue()](_value.GetPointer<void>(), func);
	}

private:

	/** Returns the index of the given type. */
	template <typename S>
	static constexpr Index IndexOf()
	{
		static_assert(Seq::template contains<S>(), "The given type does not exist in this Union.");
		return IndexOf<S>(0, Seq{});
	}

	/** Recursively finds the index of the given type. */
	template <typename S, typename C, typename ... F>
	static constexpr Index IndexOf(Index current, stde::type_sequence<C, F...>)
	{
		return std::is_same<S, C>::value ? current : IndexOf<S>(current + 1, stde::type_sequence<F...>{});
	}

	/** End case, never actually reached. */
	template <typename S>
	static constexpr Index IndexOf(Index /*current*/, stde::type_sequence<>)
	{
		return 0;
	}

	/** Creates a function that invokes a function of the given type ("Func") on a type-erased
	* instance of "F", returning an instance of "R".
	* Used by the "Invoke" method. */<commit_msg>Fixed clang errors<commit_after>// Union.h - Copyright 2013-2016 <NAME>, All Rights Reserved
#pragma once

#include <limits>
#include "../Forwards/Reflection.h"
#include "../Math/Math.h"
#include "Nullable.h"

template <typename ... T>
struct Union final
{
	///////////////////////
	///   Inner Types   ///
private:

	/** Honestly if you need a Union of more than 255 types you're doing something wrong. */
	using Index = byte;

	/** Aliasis a type_sequence holding the types supported by this Union. */
	using Seq = stde::type_sequence<T...>;

	static_assert(sizeof...(T) <= std::numeric_limits<Index>::max(), "You have too many types in this Union.");

	////////////////////////
	///   Constructors   ///
public:

	Union() = default;
	Union(const Union& copy)
		: Union()
	{
		*this = copy;
	}
	Union(Union&& move)
		: Union()
	{
		*this = std::move(move);
	}
	~Union()
	{
		Nullify();
	}

	template <typename F, WHERE(!std::is_same<std::decay_t<F>, Union>::value)>
	Union(F&& value)
		: Union()
	{
		Set(std::forward<F>(value));
	}

	///////////////////
	///   Methods   ///
public:

	/** Returns whether this Union is currently holding a value. */
	FORCEINLINE bool HasValue() const
	{
		return _index.HasValue();
	}

	/** Returns the type of the currently held value.
	* NOTE: Returns 'null' if this Union is not currently holding a value. */
	const TypeInfo* GetCurrentType() const
	{
		if (_index.HasValue())
		{
			return Invoke<const TypeInfo*>([](const auto& a) { return &TypeOf(a); });
		}
		else
		{
			return nullptr;
		}
	}

	/** Destroys the currently held value. */
	void Nullify()
	{
		if (HasValue())
		{
			// Destroy the value
			Invoke([](auto& v) -> void
			{
				using F = std::decay_t<decltype(v)>;
				v.~F();
			});
			_index.Nullify();
		}
	}

	/** Returns the current value as a Variant. 
	* WARNING: This function will fail if this Union is not currently holding a value. */
	Variant Get();

	/** Returns the current value as an ImmutableVariant. 
	* WARNING: This function will fail if this Union is not currently holding a value. */
	ImmutableVariant Get() const;

	/** Sets the current value of this Union. */
	template <typename F>
	void Set(F&& value)
	{
		using DecayF = std::decay_t<F>;
		Index newIndex = IndexOf<DecayF>();

		// If we have a currently loaded value
		if (_index.HasValue())
		{
			// If the currently loaded value is of the same type as the new value
			if (_index.GetValue() == newIndex)
			{
				// Just assign directly
				Get<DecayF>() = std::forward<F>(value);
				return;
			}
			else
			{
				// Delete current value
				Nullify();
			}
		}

		_value.template Emplace<DecayF>(std::forward<F>(value));
		_index = newIndex;
	}

	/** Gets the current value of this Union as the given type.
	* WARNING: This function will fail if this Variant is not currently holding a value of the given type. */
	template <typename F>
	F& Get()
	{
		assert(HasValue() && _index.GetValue() == IndexOf<F>());
		return *_value.template GetPointer<F>();
	}

	/** Gets the current value of this Union as the given type.
	* WARNING: This function will fail if this Variant is not currently holding a value of the given type. */
	template <typename F>
	const F& Get() const
	{
		assert(_index.HasValue() && _index.GetValue() == IndexOf<F>());
		return *_value.template GetPointer<F>();
	}

	/** Invokes the given function on the current value.
	* WARNING: If this Union is not holding a value, this function will fail. */
	template <typename R = void, typename Func>
	R Invoke(const Func& func)
	{
		using Invoker = R (void*, const Func&);	
		Invoker* funcs[] = { CreateInvoker<T, R, Func>()... };
		
		assert(HasValue());
		return funcs[_index.GetValue()](_value.GetPointer(), func);
	}

	/** Invokes the given function on the current value.
	* WARNING: If this Union is not holding a value, this function will fail. */
	template <typename R = void, typename Func>
	R Invoke(const Func& func) const
	{
		using Invoker = R (const void*, const Func&);
		Invoker* funcs[] = { CreateInvoker<T, R, Func>()... };

		assert(HasValue());
		return funcs[_index.GetValue()](_value.GetPointer(), func);
	}

private:

	/** Returns the index of the given type. */
	template <typename S>
	static constexpr Index IndexOf()
	{
		static_assert(Seq::template contains<S>(), "The given type does not exist in this Union.");
		return IndexOf<S>(0, Seq{});
	}

	/** Recursively finds the index of the given type. */
	template <typename S, typename C, typename ... F>
	static constexpr Index IndexOf(Index current, stde::type_sequence<C, F...>)
	{
		return std::is_same<S, C>::value ? current : IndexOf<S>(current + 1, stde::type_sequence<F...>{});
	}

	/** End case, never actually reached. */
	template <typename S>
	static constexpr Index IndexOf(Index /*current*/, stde::type_sequence<>)
	{
		return 0;
	}

	/** Creates a function that invokes a function of the given type ("Func") on a type-erased
	* instance of "F", returning an instance of "R".
	* Used by the "Invoke" method. */
{'fraction_non_alphanumeric': 0.157, 'fraction_numerical': 0.0028, 'mean_word_length': 3.2021008403361346, 'pattern_counts': {'":': 0, '<': 83, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3620960', 'n_tokens_mistral': 3479, 'n_tokens_neox': 3200, 'n_words': 1105}