<commit_before>#ifndef STINGRAYKIT_FUNCTION_FUNCTION_INFO_H
#define STINGRAYKIT_FUNCTION_FUNCTION_INFO_H

// Copyright (c) 2011 - 2019, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stingraykit/function/SignatureBuilder.h>
#include <stingraykit/Macro.h>

namespace stingray
{

	/**
	 * @addtogroup toolkit_functions
	 * @{
	 */

	struct FunctionType
	{
		STINGRAYKIT_ENUM_VALUES
		(
			RawFunction,
			RawFunctionPtr,
			MethodPtr,
			StingrayFunction,
			StdFunction,
			Other
		);

		STINGRAYKIT_DECLARE_ENUM_CLASS(FunctionType);
	};


#ifndef DOXYGEN_PREPROCESSOR

#define TY typename

	template < typename FuncOrRetType, typename OptionalParamTypes = NullType >
	struct function_type;


	template < typename FuncOrRetType, typename OptionalParamTypes = NullType >
	struct function_info;


///////////////////////////////////
// for raw functions and methods //
///////////////////////////////////

	template < typename R > struct function_type<R(), NullType>
	{ static const FunctionType::Enum Type = FunctionType::RawFunction; };
	template < typename R > struct function_type<R(*)(), NullType>
	{ static const FunctionType::Enum Type = FunctionType::RawFunctionPtr; };
	template < typename C, typename R > struct function_type<R (C::*)(), NullType>
	{ static const FunctionType::Enum Type = FunctionType::MethodPtr; };
	template < typename C, typename R > struct function_type<R (C::*)() const, NullType>
	{ static const FunctionType::Enum Type = FunctionType::MethodPtr; };
	template < typename R >
	struct function_info<R(), NullType> : public function_type<R()>
	{
		typedef R					RetType;
		typedef TypeList<>::type	ParamTypes;
		typedef R Signature();
	};
	template < typename R >
	struct function_info<R(*)(), NullType> : public function_type<R(*)()>
	{
		typedef R					RetType;
		typedef TypeList<>::type	ParamTypes;
		typedef R Signature();
	};
	template < typename C, typename R >
	struct function_info<R (C::*)(), NullType> : public function_type<R (C::*)()>
	{
		typedef R				RetType;
		typedef typename TypeList<C*>::type	ParamTypes;
		typedef R Signature(C*);
	};
	template < typename C, typename R >
	struct function_info<R (C::*)() const, NullType> : public function_type<R (C::*)() const>
	{
		typedef R						RetType;
		typedef typename TypeList<const C*>::type	ParamTypes;
		typedef R Signature(const C*);
	};


#define DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(ParamTypenames_, ParamTypes_) \
	template < typename R, ParamTypenames_ > struct function_type<R(ParamTypes_), NullType> \
	{ static const FunctionType::Enum Type = FunctionType::RawFunction; }; \
	template < typename R, ParamTypenames_ > struct function_type<R(*)(ParamTypes_), NullType> \
	{ static const FunctionType::Enum Type = FunctionType::RawFunctionPtr; }; \
	template < typename C, typename R, ParamTypenames_ > struct function_type<R (C::*)(ParamTypes_), NullType> \
	{ static const FunctionType::Enum Type = FunctionType::MethodPtr; }; \
	template < typename C, typename R, ParamTypenames_ > struct function_type<R (C::*)(ParamTypes_) const, NullType> \
	{ static const FunctionType::Enum Type = FunctionType::MethodPtr; }; \
	template < typename R, ParamTypenames_ > \
	struct function_info<R(ParamTypes_), NullType> : function_type<R(ParamTypes_)> \
	{ \
		typedef R										RetType; \
		typedef typename TypeList<ParamTypes_>::type	ParamTypes; \
		typedef R Signature(ParamTypes_); \
	}; \
	template < typename R, ParamTypenames_ > \
	struct function_info<R(*)(ParamTypes_), NullType> : function_type<R(*)(ParamTypes_)> \
	{ \
		typedef R										RetType; \
		typedef typename TypeList<ParamTypes_>::type	ParamTypes; \
		typedef R Signature(ParamTypes_); \
	}; \
	template < typename C, typename R, ParamTypenames_ > \
	struct function_info<R (C::*)(ParamTypes_), NullType> : function_type<R (C::*)(ParamTypes_)> \
	{ \
		typedef R											RetType; \
		typedef typename TypeList<C*, ParamTypes_>::type	ParamTypes; \
		typedef R Signature(C*, ParamTypes_); \
	}; \
	template < typename C, typename R, ParamTypenames_ > \
	struct function_info<R (C::*)(ParamTypes_) const, NullType> : function_type<R (C::*)(ParamTypes_) const> \
	{ \
		typedef R												RetType; \
		typedef typename TypeList<const C*, ParamTypes_>::type	ParamTypes; \
		typedef R Signature(const C*, ParamTypes_); \
	}

	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1), MK_PARAM(T1));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2), MK_PARAM(T1, T2));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3), MK_PARAM(T1, T2, T3));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4), MK_PARAM(T1, T2, T3, T4));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5), MK_PARAM(T1, T2, T3, T4, T5));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6), MK_PARAM(T1, T2, T3, T4, T5, T6));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6, TY T7), MK_PARAM(T1, T2, T3, T4, T5, T6, T7));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6, TY T7, TY T8), MK_PARAM(T1, T2, T3, T4, T5, T6, T7, T8));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6, TY T7, TY T8, TY T9), MK_PARAM(T1, T2, T3, T4, T5, T6, T7, T8, T9));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6, TY T7, TY T8, TY T9, TY T10), MK_PARAM(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10));

#undef DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO


////////////////////////////
// for stingray::function //
////////////////////////////

	template < typename Signature_ >
	class function;

	template < typename Signature_ >
	struct function_type<function<Signature_>, NullType>
	{ static const FunctionType::Enum Type = FunctionType::StingrayFunction; };


	template < typename Signature_ >
	struct function_info<function<Signature_>, NullType> : public function_type<function<Signature_> >
	{
		typedef typename function_info<Signature_>::RetType		RetType;
		typedef typename function_info<Signature_>::ParamTypes	ParamTypes;
		typedef typename function_info<Signature_>::Signature	Signature;
	};


//////////////////////////////////////////////
// assuming that all other are stl functors //
//////////////////////////////////////////////

	namespace Detail
	{
		STINGRAYKIT_DECLARE_NESTED_TYPE_CHECK(RetType);
		STINGRAYKIT_DECLARE_NESTED_TYPE_CHECK(ParamTypes);
		STINGRAYKIT_DECLARE_NESTED_TYPE_CHECK(result_type);

		struct FunctorType
		{
			STINGRAYKIT_ENUM_VALUES(FunctorWithRetAndParamTypes, FunctorWithRetType, StdFunctor, Other);
			STINGRAYKIT_DECLARE_ENUM_CLASS(FunctorType);
		};

		template < typename F, FunctorType::Enum FuncType =
			HasNestedType_RetType<F>::Value ? (HasNestedType_ParamTypes<F>::Value ? FunctorType::FunctorWithRetAndParamTypes : FunctorType::FunctorWithRetType) :
				HasNestedType_result_type<F>::Value ? FunctorType::StdFunctor : FunctorType::Other>
		struct FunctorTypeGetter
		{ static const FunctorType::Enum Value = FuncType; };


		template < typename F, FunctorType::Enum FuncType = FunctorTypeGetter<F>::Value >
		struct GenericFunctionType;<commit_msg>function_info: add specialization for std::function<commit_after>#ifndef STINGRAYKIT_FUNCTION_FUNCTION_INFO_H
#define STINGRAYKIT_FUNCTION_FUNCTION_INFO_H

// Copyright (c) 2011 - 2019, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stingraykit/function/SignatureBuilder.h>
#include <stingraykit/Macro.h>

#include <functional>

namespace stingray
{

	/**
	 * @addtogroup toolkit_functions
	 * @{
	 */

	struct FunctionType
	{
		STINGRAYKIT_ENUM_VALUES
		(
			RawFunction,
			RawFunctionPtr,
			MethodPtr,
			StingrayFunction,
			StdFunction,
			Other
		);

		STINGRAYKIT_DECLARE_ENUM_CLASS(FunctionType);
	};


#ifndef DOXYGEN_PREPROCESSOR

#define TY typename

	template < typename FuncOrRetType, typename OptionalParamTypes = NullType >
	struct function_type;


	template < typename FuncOrRetType, typename OptionalParamTypes = NullType >
	struct function_info;


///////////////////////////////////
// for raw functions and methods //
///////////////////////////////////

	template < typename R > struct function_type<R(), NullType>
	{ static const FunctionType::Enum Type = FunctionType::RawFunction; };
	template < typename R > struct function_type<R(*)(), NullType>
	{ static const FunctionType::Enum Type = FunctionType::RawFunctionPtr; };
	template < typename C, typename R > struct function_type<R (C::*)(), NullType>
	{ static const FunctionType::Enum Type = FunctionType::MethodPtr; };
	template < typename C, typename R > struct function_type<R (C::*)() const, NullType>
	{ static const FunctionType::Enum Type = FunctionType::MethodPtr; };
	template < typename R >
	struct function_info<R(), NullType> : public function_type<R()>
	{
		typedef R					RetType;
		typedef TypeList<>::type	ParamTypes;
		typedef R Signature();
	};
	template < typename R >
	struct function_info<R(*)(), NullType> : public function_type<R(*)()>
	{
		typedef R					RetType;
		typedef TypeList<>::type	ParamTypes;
		typedef R Signature();
	};
	template < typename C, typename R >
	struct function_info<R (C::*)(), NullType> : public function_type<R (C::*)()>
	{
		typedef R				RetType;
		typedef typename TypeList<C*>::type	ParamTypes;
		typedef R Signature(C*);
	};
	template < typename C, typename R >
	struct function_info<R (C::*)() const, NullType> : public function_type<R (C::*)() const>
	{
		typedef R						RetType;
		typedef typename TypeList<const C*>::type	ParamTypes;
		typedef R Signature(const C*);
	};


#define DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(ParamTypenames_, ParamTypes_) \
	template < typename R, ParamTypenames_ > struct function_type<R(ParamTypes_), NullType> \
	{ static const FunctionType::Enum Type = FunctionType::RawFunction; }; \
	template < typename R, ParamTypenames_ > struct function_type<R(*)(ParamTypes_), NullType> \
	{ static const FunctionType::Enum Type = FunctionType::RawFunctionPtr; }; \
	template < typename C, typename R, ParamTypenames_ > struct function_type<R (C::*)(ParamTypes_), NullType> \
	{ static const FunctionType::Enum Type = FunctionType::MethodPtr; }; \
	template < typename C, typename R, ParamTypenames_ > struct function_type<R (C::*)(ParamTypes_) const, NullType> \
	{ static const FunctionType::Enum Type = FunctionType::MethodPtr; }; \
	template < typename R, ParamTypenames_ > \
	struct function_info<R(ParamTypes_), NullType> : function_type<R(ParamTypes_)> \
	{ \
		typedef R										RetType; \
		typedef typename TypeList<ParamTypes_>::type	ParamTypes; \
		typedef R Signature(ParamTypes_); \
	}; \
	template < typename R, ParamTypenames_ > \
	struct function_info<R(*)(ParamTypes_), NullType> : function_type<R(*)(ParamTypes_)> \
	{ \
		typedef R										RetType; \
		typedef typename TypeList<ParamTypes_>::type	ParamTypes; \
		typedef R Signature(ParamTypes_); \
	}; \
	template < typename C, typename R, ParamTypenames_ > \
	struct function_info<R (C::*)(ParamTypes_), NullType> : function_type<R (C::*)(ParamTypes_)> \
	{ \
		typedef R											RetType; \
		typedef typename TypeList<C*, ParamTypes_>::type	ParamTypes; \
		typedef R Signature(C*, ParamTypes_); \
	}; \
	template < typename C, typename R, ParamTypenames_ > \
	struct function_info<R (C::*)(ParamTypes_) const, NullType> : function_type<R (C::*)(ParamTypes_) const> \
	{ \
		typedef R												RetType; \
		typedef typename TypeList<const C*, ParamTypes_>::type	ParamTypes; \
		typedef R Signature(const C*, ParamTypes_); \
	}

	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1), MK_PARAM(T1));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2), MK_PARAM(T1, T2));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3), MK_PARAM(T1, T2, T3));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4), MK_PARAM(T1, T2, T3, T4));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5), MK_PARAM(T1, T2, T3, T4, T5));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6), MK_PARAM(T1, T2, T3, T4, T5, T6));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6, TY T7), MK_PARAM(T1, T2, T3, T4, T5, T6, T7));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6, TY T7, TY T8), MK_PARAM(T1, T2, T3, T4, T5, T6, T7, T8));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6, TY T7, TY T8, TY T9), MK_PARAM(T1, T2, T3, T4, T5, T6, T7, T8, T9));
	DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO(MK_PARAM(TY T1, TY T2, TY T3, TY T4, TY T5, TY T6, TY T7, TY T8, TY T9, TY T10), MK_PARAM(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10));

#undef DETAIL_STINGRAYKIT_DECLARE_FUNCTION_INFO


////////////////////////////
// for stingray::function //
////////////////////////////

	template < typename Signature_ >
	class function;

	template < typename Signature_ >
	struct function_type<function<Signature_>, NullType>
	{ static const FunctionType::Enum Type = FunctionType::StingrayFunction; };


	template < typename Signature_ >
	struct function_info<function<Signature_>, NullType> : public function_type<function<Signature_> >
	{
		typedef typename function_info<Signature_>::RetType		RetType;
		typedef typename function_info<Signature_>::ParamTypes	ParamTypes;
		typedef typename function_info<Signature_>::Signature	Signature;
	};


///////////////////////
// for std::function //
///////////////////////

	template < typename Signature_ >
	struct function_type<std::function<Signature_>, NullType>
	{ static const FunctionType::Enum Type = FunctionType::StdFunction; };


	template < typename Signature_ >
	struct function_info<std::function<Signature_>, NullType> : public function_type<function<Signature_> >
	{
		typedef typename function_info<Signature_>::RetType		RetType;
		typedef typename function_info<Signature_>::ParamTypes	ParamTypes;
		typedef typename function_info<Signature_>::Signature	Signature;
	};


//////////////////////////////////////////////
// assuming that all other are stl functors //
//////////////////////////////////////////////

	namespace Detail
	{
		STINGRAYKIT_DECLARE_NESTED_TYPE_CHECK(RetType);
		STINGRAYKIT_DECLARE_NESTED_TYPE_CHECK(ParamTypes);
		STINGRAYKIT_DECLARE_NESTED_TYPE_CHECK(result_type);

		struct FunctorType
		{
			STINGRAYKIT_ENUM_VALUES(FunctorWithRetAndParamTypes, FunctorWithRetType, StdFunctor, Other);
			STINGRAYKIT_DECLARE_ENUM_CLASS(FunctorType);
		};

		template < typename F, FunctorType::Enum FuncType =
			HasNestedType_RetType<F>::Value ? (HasNestedType_ParamTypes<F>::Value ? FunctorType::FunctorWithRetAndParamTypes : FunctorType::FunctorWithRetType) :
				HasNestedType_result_type<F>::Value ? FunctorType::StdFunctor : FunctorType::Other>
		struct FunctorTypeGetter
		{ static const FunctorType::Enum Value = FuncType; };


		template < typename F, FunctorType::Enum FuncType = FunctorTypeGetter<F>::Value >
		struct GenericFunctionType;
{'fraction_non_alphanumeric': 0.13750982644977927, 'fraction_numerical': 0.014512910443248473, 'mean_word_length': 4.445505432993086, 'pattern_counts': {'":': 0, '<': 155, '<?xml version=': 0, '>': 155, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '654533', 'n_tokens_mistral': 6155, 'n_tokens_neox': 5522, 'n_words': 1430}