<commit_before>#ifndef STINGRAY_TOOLKIT_VARIANT_H
#define STINGRAY_TOOLKIT_VARIANT_H


#include <stingray/toolkit/MetaProgramming.h>
#include <stingray/toolkit/any.h>


namespace stingray
{

	template < typename Typelist_ >
	class variant
	{
		template<typename T, typename SomeTypelist_> friend T* variant_get(variant<SomeTypelist_>* v);
		template<typename T, typename SomeTypelist_> friend const T* variant_get(const variant<SomeTypelist_>* v);
		template<typename T, typename SomeTypelist_> friend T& variant_get(variant<SomeTypelist_>& v);
		template<typename T, typename SomeTypelist_> friend const T& variant_get(const variant<SomeTypelist_>& v);
	
		typedef typename GetTypeListItem<Typelist_, 0>::ValueT	DefaultType;

		template < int N >
		struct WhichFunc
		{
			static bool Call(const any* data, int& result)
			{
				if (!any_cast<typename GetTypeListItem<Typelist_, N>::ValueT>(data))
					return true;

				result = N;
				return false; // break the loop
			}
		};

	private:
		any _data; // TODO: reimplement

	public:
		typedef Typelist_ typelist;

		variant()
			: _data(DefaultType())
		{ }

		template < typename T >
		variant(const T &val)
			: _data(val)
		{ CompileTimeAssert<TypeListContains<Typelist_, T>::Value> ERROR__invalid_type_for_variant; }

		//template < typename OtherTypelist > 
		//variant(const variant<OtherTypelist>& other);

		void swap(variant& other)
		{ std::swap(_data, other._data); }

		variant & operator= (const variant& other)
		{
			variant tmp(other);
			swap(tmp);
			return *this;
		}
		
		template<typename T>
		variant & operator= (const T & val)
		{
			variant tmp(val);
			swap(tmp);
			return *this;
		}

		int which() const
		{
			int result = -1;
			ForIf<GetTypeListLength<Typelist_>::Value, WhichFunc>::Do(&_data, ref(result));
			return result;
		}

		bool empty() const
		{ return _data.empty(); }

		//const std::type_info & type() const;

		//bool operator==(const variant &) const;
		//template<typename U> void operator==(const U &) const;

		//bool operator<(const variant &) const;
		//template<typename U> void operator<(const U &) const;
	};

	class bad_variant_get : public std::bad_cast
	{
	private:
		std::string		_message;
	public:
		bad_variant_get(const std::string& to) : _message("Bad 'variant' get (" + to + " type requested)!") { }
		virtual ~bad_variant_get() throw() { }

		virtual const char* what() const throw() { return _message.c_str(); }
	};


	template<typename T, typename Typelist_> 
	T* variant_get(variant<Typelist_>* v)
	{
		CompileTimeAssert<TypeListContains<Typelist_, T>::Value> ERROR__invalid_type_for_variant;
		try { return v ? any_cast<T>(&v->_data) : NULL; }<commit_msg>variant::type() method<commit_after>#ifndef STINGRAY_TOOLKIT_VARIANT_H
#define STINGRAY_TOOLKIT_VARIANT_H


#include <typeinfo>

#include <stingray/toolkit/MetaProgramming.h>
#include <stingray/toolkit/any.h>


namespace stingray
{

	template < typename Typelist_ >
	class variant
	{
		template<typename T, typename SomeTypelist_> friend T* variant_get(variant<SomeTypelist_>* v);
		template<typename T, typename SomeTypelist_> friend const T* variant_get(const variant<SomeTypelist_>* v);
		template<typename T, typename SomeTypelist_> friend T& variant_get(variant<SomeTypelist_>& v);
		template<typename T, typename SomeTypelist_> friend const T& variant_get(const variant<SomeTypelist_>& v);
	
		typedef typename GetTypeListItem<Typelist_, 0>::ValueT	DefaultType;

		template < int N >
		struct WhichFunc
		{
			static bool Call(const any* data, int& result)
			{
				if (!any_cast<typename GetTypeListItem<Typelist_, N>::ValueT>(data))
					return true;

				result = N;
				return false; // break the loop
			}
		};

		template < int N >
		struct GetTypeInfoFunc
		{
			static bool Call(const any* data, const std::type_info*& result)
			{
				typedef typename GetTypeListItem<Typelist_, N>::ValueT	Type;
				if (!any_cast<Type>(data))
					return true;

				result = &typeid(Type);
				return false; // break the loop
			}
		};

	private:
		any _data; // TODO: reimplement

	public:
		typedef Typelist_ typelist;

		variant()
			: _data(DefaultType())
		{ }

		template < typename T >
		variant(const T &val)
			: _data(val)
		{ CompileTimeAssert<TypeListContains<Typelist_, T>::Value> ERROR__invalid_type_for_variant; }

		//template < typename OtherTypelist > 
		//variant(const variant<OtherTypelist>& other);

		void swap(variant& other)
		{ std::swap(_data, other._data); }

		variant & operator= (const variant& other)
		{
			variant tmp(other);
			swap(tmp);
			return *this;
		}
		
		template<typename T>
		variant & operator= (const T & val)
		{
			variant tmp(val);
			swap(tmp);
			return *this;
		}

		int which() const
		{
			int result = -1;
			ForIf<GetTypeListLength<Typelist_>::Value, WhichFunc>::Do(&_data, ref(result));
			return result;
		}

		bool empty() const
		{ return _data.empty(); }

		const std::type_info & type() const
		{
			const std::type_info* result = NULL;
			ForIf<GetTypeListLength<Typelist_>::Value, GetTypeInfoFunc>::Do(&_data, ref(result));
			return *TOOLKIT_REQUIRE_NOT_NULL(result);
		}

		//bool operator==(const variant &) const;
		//template<typename U> void operator==(const U &) const;

		//bool operator<(const variant &) const;
		//template<typename U> void operator<(const U &) const;
	};

	class bad_variant_get : public std::bad_cast
	{
	private:
		std::string		_message;
	public:
		bad_variant_get(const std::string& to) : _message("Bad 'variant' get (" + to + " type requested)!") { }
		virtual ~bad_variant_get() throw() { }

		virtual const char* what() const throw() { return _message.c_str(); }
	};


	template<typename T, typename Typelist_> 
	T* variant_get(variant<Typelist_>* v)
	{
		CompileTimeAssert<TypeListContains<Typelist_, T>::Value> ERROR__invalid_type_for_variant;
		try { return v ? any_cast<T>(&v->_data) : NULL; }
{'fraction_non_alphanumeric': 0.12840599455040871, 'fraction_numerical': 0.0006811989100817438, 'mean_word_length': 4.324569356300997, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 71, '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': '698502', 'n_tokens_mistral': 2291, 'n_tokens_neox': 1939, 'n_words': 477}