summaryrefslogtreecommitdiff
path: root/TypeExtend.h
diff options
context:
space:
mode:
Diffstat (limited to 'TypeExtend.h')
-rw-r--r--TypeExtend.h1280
1 files changed, 1280 insertions, 0 deletions
diff --git a/TypeExtend.h b/TypeExtend.h
new file mode 100644
index 0000000..4a6444e
--- /dev/null
+++ b/TypeExtend.h
@@ -0,0 +1,1280 @@
+#pragma once
+
+//±ê×¼¿âÀàÐÍÀ©Õ¹²Ù×÷
+//20191212-1029
+
+#include <cassert>
+#include <cmath>
+#include <cstdint>
+
+#include <type_traits>
+#include <limits>
+#include <algorithm>
+#include <utility>
+#include <tuple>
+#include <functional>
+#include <iterator>
+
+#include <string>
+
+#include <exception>
+#include <stdexcept>
+#include <random>
+#include <ratio>
+
+#include <chrono>
+
+
+
+
+//************
+//ÀàÐͱðÃûÀ©Õ¹
+//************
+
+
+//durationÀ©Õ¹
+namespace std
+{
+namespace chrono
+{
+typedef duration<long, ratio<3600*24>> days;
+typedef duration<long, ratio<3600*24*7>> weeks;
+}
+}
+
+
+
+//************
+//»ù´¡ÀàÐÍÀ©Õ¹
+//************
+
+//ÎÞÓÃռλÀàÐÍ
+template<int N>
+class BlankType
+{
+};
+
+
+
+//²âÊÔ²ÎÊýÊÇ·ñºÏ·¨Àà
+template<typename ...>
+struct ParamValidTester
+{
+ typedef void type;
+};
+
+
+//ÏÈÈ¥³ýÒýÓÃÔÙÈ¥³ý³£ÊýÒ×±äÊôÐÔ
+template<typename Ty>
+struct RemoveCVRef
+{
+ using type = typename std::remove_cv<typename std::remove_reference<Ty>::type>::type;
+};
+
+//ºóÕßÈ¥³ýÒýÓó£ÊýÒ×±äºóÊÇ·ñΪǰÕß
+template<typename TyDst, typename TySrc>
+struct IsRemoveCVRefSame:
+ std::is_same<TyDst, typename RemoveCVRef<TySrc>::type>
+{
+};
+
+
+//ºóÕß²ÎÊý°üÊÇ·ñÒª²»Ã»ÓвÎÊý£¬Òª²»Ö»ÓÐÒ»¸ö²¢ÇÒΪǰÕß
+template<typename TyDst, typename ...TySrc_S>
+struct IsNoneOrSame:
+ std::integral_constant<bool, sizeof...(TySrc_S)==0>
+{
+};
+template<typename TyDst, typename TySrc>
+struct IsNoneOrSame<TyDst, TySrc>:
+ std::is_same<TyDst, TySrc>
+{
+};
+
+//ºóÕß²ÎÊý°üÊÇ·ñÒª²»Ã»ÓвÎÊý£¬Òª²»Ö»ÓÐÒ»¸ö²¢ÇÒÈ¥³ýÒýÓó£ÊýÒ×±äºóΪǰÕß
+template<typename TyDst, typename ...TySrc_S>
+struct IsNoneOrRemoveCVRefSame:
+ std::integral_constant<bool, sizeof...(TySrc_S)==0>
+{
+};
+template<typename TyDst, typename TySrc>
+struct IsNoneOrRemoveCVRefSame<TyDst, TySrc>:
+ IsRemoveCVRefSame<TyDst, TySrc>
+{
+};
+
+
+//²âÊÔÊÇ·ñΪµü´úÆ÷
+template<class Ty, class= void>
+struct IsIteratorType:
+ std::false_type
+{
+};
+template<class Ty>
+struct IsIteratorType<Ty, typename ParamValidTester<
+ typename std::iterator_traits<Ty>::iterator_category>::type
+>: std::true_type
+{
+};
+
+
+//²âÊÔÈ¥³ý³£Ò×±äÒ×ÓÃÊôÐÔºó£¬ÊÇ·ñΪ×Ö·ûÖ¸Õ룬×Ö·ûÊý×é»òstringÀàÐÍ
+template<class Ty>
+struct IsRemoveCVRefSameSzOrString:
+ std::integral_constant<bool, IsRemoveCVRefSame<char *, Ty>::value
+ || IsRemoveCVRefSame<const char *, Ty>::value
+ || (std::is_array<typename RemoveCVRef<Ty>::type>::value
+ && IsRemoveCVRefSame<char, typename std::remove_extent<
+ typename RemoveCVRef<Ty>::type>::type>::value)
+ || IsRemoveCVRefSame<std::string, Ty>::value>
+{
+};
+
+
+
+//Éú³Éµü´úÆ÷½âÒýÓõÄÀàÐÍ£¬±£Áô³£Ò×±äÒýÓÃÊôÐÔ
+template<typename TyIt>
+struct IteratorDerefType
+{
+ using type = decltype(*std::declval<TyIt>());
+};
+
+//Éú³Éµü´úÆ÷½âÒýÓõÄÀàÐÍÔÙÈ¥³ý³£Ò×±äÒýÓÃÊôÐÔ
+template<typename TyIt>
+struct IteratorRemoveCVRefDerefType
+{
+ using type = typename RemoveCVRef<typename IteratorDerefType<TyIt>::type>::type;
+};
+
+
+
+//¸ù¾ÝÌṩÀ´Ô´ÀàÐ͵ÄÒýÓᢳ£Êý¡¢Ò×±äÊôÐÔ£¬¶ÔÄ¿µÄÀàÐ͸½¼ÓͬÑùµÄÊôÐÔ
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute
+{
+ using type = TyDst;
+};
+//³£ÊôÐÔÌØ»¯
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute<const TySrc, TyDst>
+{
+ using type = typename std::add_const<
+ typename TypeAttachAttribute<TySrc, TyDst>::type>::type;
+};
+//Ò×±äÊôÐÔÌØ»¯
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute<volatile TySrc, TyDst>
+{
+ using type = typename std::add_volatile<
+ typename TypeAttachAttribute<TySrc, TyDst>::type>::type;
+};
+//×óÖµÒýÓÃÊôÐÔÌØ»¯
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute<TySrc &, TyDst>
+{
+ using type = typename std::add_lvalue_reference<
+ typename TypeAttachAttribute<TySrc, TyDst>::type>::type;
+};
+//ÓÒÖµÒýÓÃÊôÐÔÌØ»¯
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute<TySrc &&, TyDst>
+{
+ using type = typename std::add_rvalue_reference<
+ typename TypeAttachAttribute<TySrc, TyDst>::type>::type;
+};
+
+
+
+//Çóµ÷Ó÷µ»ØÖµÀàÐÍ
+template<typename TyFunc, typename ...Ty_S>
+struct InvokeReturnType
+{
+ using type = decltype(std::declval<TyFunc>()(std::declval<Ty_S>()...));
+};
+
+
+
+//ÕûÊýÐòÁÐÄ£°å
+template<size_t ...c_idx_s>
+struct IndexSequence
+{
+};
+template<>
+struct IndexSequence<>
+{
+ using value_type = size_t;
+ static constexpr size_t size()
+ {
+ return 0;
+ }
+};
+template<int c_idx, int ...c_rest_s>
+struct IndexSequence<c_idx, c_rest_s...>
+{
+ using value_type = size_t;
+ static constexpr size_t size()
+ {
+ return IndexSequence<c_rest_s...>::size()+1;
+ }
+};
+
+//ÕûÊýÄ£°åÌí¼ÓÔªËØº¯Êý
+template<size_t c_new, size_t ...c_idx_s>
+inline IndexSequence<c_idx_s..., c_new> AddIndexSequence(IndexSequence<c_idx_s...>)
+{
+ return IndexSequence<c_idx_s..., c_new>();
+}
+
+//Éú³É˳ÐòµÝÔöÕûÊýÄ£°å¸¨ÖúÀà
+template<size_t c_size>
+struct _MakeIndexSequenceAssist
+{
+ using type = decltype(AddIndexSequence<c_size-1>(
+ typename _MakeIndexSequenceAssist<c_size-1>::type()));
+};
+template<>
+struct _MakeIndexSequenceAssist<0>
+{
+ using type = IndexSequence<>;
+};
+//Éú³É˳ÐòµÝÔöÕûÊýÄ£°åÀà
+template<size_t c_size>
+using MakeIndexSequence = typename _MakeIndexSequenceAssist<c_size>::type;
+
+
+
+//Ä£°å¶¨³¤ÕûÐÎ
+template<bool c_bSigned, int c_size>
+struct TemplateInt
+{
+};
+template<>
+struct TemplateInt<true, 1>
+{
+ using type = int8_t;
+};
+template<>
+struct TemplateInt<false, 1>
+{
+ using type = uint8_t;
+};
+template<>
+struct TemplateInt<true, 2>
+{
+ using type = int16_t;
+};
+template<>
+struct TemplateInt<false, 2>
+{
+ using type = uint16_t;
+};
+template<>
+struct TemplateInt<true, 4>
+{
+ using type = int32_t;
+};
+template<>
+struct TemplateInt<false, 4>
+{
+ using type = uint32_t;
+};
+template<>
+struct TemplateInt<true, 8>
+{
+ using type = int64_t;
+};
+template<>
+struct TemplateInt<false, 8>
+{
+ using type = uint64_t;
+};
+
+
+
+//¹ãÒåµÄ±È½Ïº¯ÊýÀà
+template<typename Ty1, typename Ty2= Ty1>
+struct GeneralLess
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return arg1<arg2;
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct GeneralEqualTo
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return arg1==arg2;
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct GeneralLessEqual
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return arg1<=arg2;
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct GeneralGreater
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return arg1>arg2;
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct GeneralGreaterEqual
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return arg1>=arg2;
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct GeneralNotEqualTo
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return arg1!=arg2;
+ }
+};
+
+
+//À©Õ¹µÄ¹ãÒå±È½Ïº¯ÊýÀ࣬ʹÓÃСÓں͵ÈÓÚ²Ù×÷ÔËËã
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendGeneralLessEqual
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return arg1<arg2 || arg1==arg2;
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendGeneralGreater
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return !(arg1<arg2 || arg1==arg2);
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendGeneralGreaterEqual
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return !(arg1<arg2);
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendGeneralNotEqualTo
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return !(arg1==arg2);
+ }
+};
+
+
+//±È½ÏÀàÐ͵ĺ¯Êý·â×°
+template<typename Ty1, typename Ty2= Ty1>
+using CompareType = std::function<bool(const Ty1 &, const Ty2 &)>;
+
+
+//±È½ÏÀຯÊýÀ©Õ¹£¬Ê¹ÓÃСÓں͵ÈÓÚº¯Êý
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendLessEqualWrap
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+public:
+ CompareType<Ty1, Ty2> funcLT;
+ CompareType<Ty1, Ty2> funcEQ;
+public:
+ explicit ExtendLessEqualWrap(const CompareType<Ty1, Ty2> &o_funcLT,
+ const CompareType<Ty1, Ty2> &o_funcEQ)
+ :
+ funcLT(o_funcLT), funcEQ(o_funcEQ)
+ {
+ }
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return funcLT(arg1, arg2) || funcEQ(arg1, arg2);
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendGreaterWrap
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+public:
+ CompareType<Ty1, Ty2> funcLT;
+ CompareType<Ty1, Ty2> funcEQ;
+public:
+ explicit ExtendGreaterWrap(const CompareType<Ty1, Ty2> &o_funcLT,
+ const CompareType<Ty1, Ty2> &o_funcEQ)
+ :
+ funcLT(o_funcLT), funcEQ(o_funcEQ)
+ {
+ }
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return !(funcLT(arg1, arg2) || funcEQ(arg1, arg2));
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendGreaterEqualWrap
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+public:
+ CompareType<Ty1, Ty2> funcLT;
+ CompareType<Ty1, Ty2> funcEQ;
+public:
+ explicit ExtendGreaterEqualWrap(const CompareType<Ty1, Ty2> &o_funcLT,
+ const CompareType<Ty1, Ty2> &o_funcEQ)
+ :
+ funcLT(o_funcLT), funcEQ(o_funcEQ)
+ {
+ }
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return !funcLT(arg1, arg2);
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendNotEqualToWrap
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+public:
+ CompareType<Ty1, Ty2> funcLT;
+ CompareType<Ty1, Ty2> funcEQ;
+public:
+ explicit ExtendNotEqualToWrap(const CompareType<Ty1, Ty2> &o_funcLT,
+ const CompareType<Ty1, Ty2> &o_funcEQ)
+ :
+ funcLT(o_funcLT), funcEQ(o_funcEQ)
+ {
+ }
+ result_type operator()(const first_argument_type &arg1,
+ const second_argument_type &arg2) const
+ {
+ return !funcEQ(arg1, arg2);
+ }
+};
+
+
+
+//´æ´¢Ä³ÀàÐÍ£¬¿ÉÒÔΪֵ»òÒýÓ㬶Ը÷ÖÖÇé¿öÒѽøÐÐÌØ»¯
+//ÖµÀàÐÍÌØ»¯
+template<typename Ty>
+struct TypeHolder
+{
+ Ty hold;
+public:
+ //¹¹Ôì
+ TypeHolder(const Ty &o_hold):
+ hold(o_hold)
+ {
+ }
+ TypeHolder(Ty &&o_hold):
+ hold(std::move(o_hold))
+ {
+ }
+};
+//×óÖµÒýÓÃÌØ»¯
+template<typename Ty>
+struct TypeHolder<Ty &>
+{
+ Ty &hold;
+public:
+ //¹¹Ôì
+ TypeHolder(Ty &o_hold):
+ hold(o_hold)
+ {
+ }
+};
+//ÓÒÖµÒýÓÃÌØ»¯
+template<typename Ty>
+struct TypeHolder<Ty &&>
+{
+ Ty &&hold;
+public:
+ //¹¹Ôì
+ TypeHolder(Ty &&o_hold):
+ hold(std::move(o_hold))
+ {
+ }
+};
+
+
+
+//´æ´¢Ä³ÖµÀàÐÍ£¬²»ÄÜΪÒýÓã¬ÀàÐÍÖ§³Övoid
+template<typename Ty>
+struct ValueHolder
+{
+public:
+ using RefType = Ty &;
+ using ConstRefType = const Ty &;
+ using PtrType = Ty *;
+ using ConstPtrType = const Ty *;
+public:
+ Ty hold;
+public:
+ //Ä£°å¹¹Ôì
+ template<typename ...Ty_S>
+ explicit ValueHolder(Ty_S &&...args):
+ hold(std::forward<Ty_S>(args)...)
+ {
+ }
+};
+//voidÌØ»¯
+template<>
+struct ValueHolder<void>
+{
+ using RefType = void;
+ using ConstRefType = void;
+ using PtrType = void;
+ using ConstPtrType = void;
+};
+
+
+
+//**********************
+//ÀàÐͳÉÔ±»ò¸¨Öúº¯ÊýÀ©Õ¹
+//**********************
+
+//µ÷ÓñäÁ¿µÄÎö¹¹º¯Êý
+template<typename Ty>
+inline void CallDestruct(Ty &value)
+{
+ value.~Ty();
+}
+
+//µ÷ÓñäÁ¿µÄ¹¹Ô캯Êý£¬ÒªÇó±äÁ¿ÒѾ­Îö¹¹
+template<typename Ty, typename ...Ty_S>
+inline void CallConstruct(Ty &value, Ty_S &&...arg_s)
+{
+ new(&value) Ty(std::forward<Ty_S>(arg_s)...);
+}
+
+//µ÷ÓñäÁ¿µÄÎö¹¹º¯ÊýºÍ¹¹Ô캯Êý
+template<typename Ty, typename ...Ty_S>
+inline void CallRestruct(Ty &value, Ty_S &&...arg_s)
+{
+ CallDestruct(value);
+ CallConstruct(value, std::forward<Ty_S>(arg_s)...);
+}
+
+
+
+//ÌáÈ¡±äÁ¿µÄ×óÖµÒýÓÃ
+template<typename Ty>
+inline Ty &GetLref(Ty &&value)
+{
+ return value;
+}
+//ÌáÈ¡±äÁ¿µÄ³£×óÖµÒýÓÃ
+template<typename Ty>
+inline const Ty &GetConstLref(Ty &&value)
+{
+ return value;
+}
+
+
+//¶Ô±äÁ¿½øÐÐÖµ¿½±´
+template<typename Ty>
+inline Ty GetValueCopy(const Ty &value)
+{
+ return Ty(value);
+}
+
+
+
+//c·ç¸ñ×Ö·û´®×ª»¯×Ö·û´®£¬×Ö·ûÖ¸ÕëÖØÔØ
+inline std::string OverrideSzToStr(const char *sz)
+{
+ return std::string(sz);
+}
+inline std::string OverrideSzToStr(char *sz)
+{
+ return std::string(sz);
+}
+//c·ç¸ñ×Ö·û´®×ª»¯×Ö·û´®£¬×Ö·ûÊý×éÖØÔØ
+template<typename Ty>
+inline typename std::enable_if<std::is_array<typename RemoveCVRef<Ty>::type>::value
+ && IsRemoveCVRefSame<char, typename std::remove_extent<
+ typename RemoveCVRef<Ty>::type>::type>::value, std::string
+>::type OverrideSzToStr(Ty &&sz)
+{
+ return std::string(std::forward<Ty>(sz));
+}
+//c·ç¸ñ×Ö·û´®×ª»¯×Ö·û´®£¬ÆäÓàÇé¿öÖØÔØ
+template<typename Ty>
+inline Ty &&OverrideSzToStr(Ty &&arg)
+{
+ return std::forward<Ty>(arg);
+}
+
+
+
+//ÕûÐαȽϸ¨Öúºê
+#define _IS_INT_TYPE(Ty1, Ty2) \
+ (std::is_integral<Ty1>::value && std::is_integral<Ty2>::value)
+#define _INT_SIGN_UNSIGN(Ty1, Ty2) \
+ ((std::is_integral<Ty1>::value && std::is_signed<Ty1>::value)\
+ && std::is_unsigned<Ty2>::value)
+
+//ÕûÐÎÀàÐͰ²È«ÅжÏСÓÚ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty1, Ty2), bool
+>::type IntLT(Ty1 num1, Ty2 num2)
+{
+ return (num1<0) ? (true)
+ : (static_cast<typename std::make_unsigned<Ty1>::type>(num1)<num2);
+}
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty2, Ty1), bool
+>::type IntLT(Ty1 num1, Ty2 num2)
+{
+ return (num2<0) ? (false)
+ : (num1<static_cast<typename std::make_unsigned<Ty2>::type>(num2));
+}
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2)
+ && !_INT_SIGN_UNSIGN(Ty1, Ty2) && !_INT_SIGN_UNSIGN(Ty2, Ty1), bool
+>::type IntLT(Ty1 num1, Ty2 num2)
+{
+ return num1<num2;
+}
+
+//ÕûÐÎÀàÐͰ²È«ÅжϵÈÓÚ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty1, Ty2), bool
+>::type IntEQ(Ty1 num1, Ty2 num2)
+{
+ return (num1<0) ? (false)
+ : (static_cast<typename std::make_unsigned<Ty1>::type>(num1)==num2);
+}
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty2, Ty1), bool
+>::type IntEQ(Ty1 num1, Ty2 num2)
+{
+ return (num2<0) ? (false)
+ : (num1==static_cast<typename std::make_unsigned<Ty2>::type>(num2));
+}
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2)
+ && !_INT_SIGN_UNSIGN(Ty1, Ty2) && !_INT_SIGN_UNSIGN(Ty2, Ty1), bool
+>::type IntEQ(Ty1 num1, Ty2 num2)
+{
+ return num1==num2;
+}
+
+//ÕûÐÎÀàÐͰ²È«ÅжÏСÓÚµÈÓÚ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool
+>::type IntLTE(Ty1 num1, Ty2 num2)
+{
+ return IntLT(num1, num2) || IntEQ(num1, num2);
+}
+
+//ÕûÐÎÀàÐͰ²È«ÅжϴóÓÚ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool
+>::type IntGT(Ty1 num1, Ty2 num2)
+{
+ return !(IntLT(num1, num2) || IntEQ(num1, num2));
+}
+
+//ÕûÐÎÀàÐͰ²È«ÅжϴóÓÚµÈÓÚ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool
+>::type IntGTE(Ty1 num1, Ty2 num2)
+{
+ return !IntLT(num1, num2);
+}
+
+//ÕûÐÎÀàÐͰ²È«Åжϲ»µÈÓÚ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool
+>::type IntNEQ(Ty1 num1, Ty2 num2)
+{
+ return !IntEQ(num1, num2);
+}
+#undef _IS_INT_TYPE
+#undef _INT_SIGN_UNSIGN
+
+
+
+//¸¡µãÊý±È½Ï¸¨Öúºê
+#define _FLOAT_DEFAULT_ULP 10
+#define _FLOAT_DEFAULT_ABS_MODE true
+#define _IS_FLOAT_TYPE(Ty1, Ty2) \
+ (std::is_floating_point<Ty1>::value && std::is_floating_point<Ty2>::value)
+#define _FLOAT_COMMON_EPSILON(Ty1, Ty2) \
+ (std::max(std::numeric_limits<Ty1>::epsilon(), std::numeric_limits<Ty2>::epsilon()))
+#define _FLOAT_COMMON_MIN(Ty1, Ty2) \
+ (std::max(std::numeric_limits<Ty1>::min(), std::numeric_limits<Ty2>::min()))
+#define _FLOAT_ABS(num) ((num)>=0? (num):-(num))
+
+//¸¡µãÊý±È½ÏÏàµÈ£¬±£Ö¤Âß¼­¹ØÏµ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool
+>::type FloatEQ(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP)
+{
+ return bAbs ?
+ (_FLOAT_ABS(num1-num2)<_FLOAT_COMMON_EPSILON(Ty1, Ty2)*ulp)
+ :
+ (_FLOAT_ABS(num1-num2)<_FLOAT_COMMON_EPSILON(Ty1, Ty2)
+ *(_FLOAT_ABS(num1)+_FLOAT_ABS(num2))*ulp
+ || _FLOAT_ABS(num1-num2)<_FLOAT_COMMON_MIN(Ty1, Ty2)*ulp);
+}
+
+//¸¡µãÊý±È½ÏСÓÚ£¬±£Ö¤Âß¼­¹ØÏµ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool
+>::type FloatLT(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP)
+{
+ return num1<num2 && !FloatEQ(num1, num2, bAbs, ulp);
+}
+
+//¸¡µãÊý±È½ÏСÓÚµÈÓÚ£¬±£Ö¤Âß¼­¹ØÏµ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool
+>::type FloatLTE(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP)
+{
+ return FloatLT(num1, num2, bAbs, ulp) || FloatEQ(num1, num2, bAbs, ulp);
+}
+
+//¸¡µãÊý±È½Ï´óÓÚ£¬±£Ö¤Âß¼­¹ØÏµ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool
+>::type FloatGT(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP)
+{
+ return !(FloatLT(num1, num2, bAbs, ulp) || FloatEQ(num1, num2, bAbs, ulp));
+}
+
+//¸¡µãÊý±È½Ï´óÓÚµÈÓÚ£¬±£Ö¤Âß¼­¹ØÏµ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool
+>::type FloatGTE(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP)
+{
+ return !FloatLT(num1, num2, bAbs, ulp);
+}
+
+//¸¡µãÊý±È½Ï²»µÈÓÚ£¬±£Ö¤Âß¼­¹ØÏµ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool
+>::type FloatNEQ(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP)
+{
+ return !FloatEQ(num1, num2, bAbs, ulp);
+}
+
+
+//¸¡µãÊýÏÂת»¯ÕûÊý
+template<typename Ty>
+inline typename std::enable_if<std::is_floating_point<Ty>::value, Ty
+>::type FloatFloor(Ty num, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP)
+{
+ Ty res = std::round(num);
+ if(FloatEQ(num, res, bAbs, ulp))
+ return res;
+ return std::floor(num);
+}
+
+//¸¡µãÊýÉÏת»¯ÕûÊý
+template<typename Ty>
+inline typename std::enable_if<std::is_floating_point<Ty>::value, Ty
+>::type FloatCeil(Ty num, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP)
+{
+ Ty res = std::round(num);
+ if(FloatEQ(num, res, bAbs, ulp))
+ return res;
+ return std::ceil(num);
+}
+#undef _FLOAT_DEFAULT_ULP
+#undef _IS_FLOAT_TYPE
+#undef _FLOAT_COMMON_EPSILON
+#undef _FLOAT_COMMON_MIN
+#undef _FLOAT_ABS
+
+
+
+//stringµÄÀÛ¼Ó²Ù×÷£¬Ê¹ÓÃ×óÒÆÔËËã·û
+template<typename Ele, typename Ty>
+inline std::string &operator <<(std::basic_string<Ele> &str, Ty &&arg)
+{
+ return str += std::forward<Ty>(arg);
+}
+
+
+
+//·¶Î§ÄÚ×ÖµäÐò±È½Ï²Ù×÷£¬Ê¹Óõü´úÆ÷£¬Ð¡ÓÚµÈÓÚ´óÓڷֱ𷵻Ø-1,0,1
+template<typename TyIt1, typename TyIt2,
+ typename TyLess= GeneralLess<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::type>,
+ typename TyEqual= GeneralEqualTo<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::type>
+> inline int SequenceCompare(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2,
+ TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual())
+{
+ for(; ; ++st1, ++st2) {
+ //ÅжϽáÊøÌõ¼þ
+ if(st1==ed1) {
+ if(st2==ed2)
+ return 0;
+ else
+ return -1;
+ }
+ else if(st2==ed2)
+ return 1;
+ //ÅжϴóС
+ if(funcLess(*st1, *st2))
+ return -1;
+ else if(!(funcEqual(*st1, *st2)))
+ return 1;
+ }
+}
+
+
+
+//¼ì²éÊÇ·ñΪtupleÀà
+template<typename Ty>
+struct IsTupleType:
+ std::false_type
+{
+};
+template<typename ...Ty_S>
+struct IsTupleType<std::tuple<Ty_S...>>:
+ std::true_type
+{
+};
+
+
+//tupleÀàÐÍת»»À©Õ¹¸¨Öúº¯Êý
+template<typename TyDst, typename TySrc, size_t ...c_idx_s>
+inline TyDst _TupleCastAssist(TySrc &&src, IndexSequence<c_idx_s...>)
+{
+ return TyDst(std::get<c_idx_s>(std::forward<TySrc>(src))...);
+}
+//tupleÀàÐÍת»»À©Õ¹£¬Ö±½ÓÍêÃÀת·¢ÒÔÖ§³ÖËùÓеÄÒýÓÃÇé¿ö£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë
+//Ô´ÀàÐÍÐèÒªÄܱ»getº¯Êý²ð½â£¬Ä¿µÄÀàÐÍÐèÒªÄܽÓÊÜÔ´ÀàÐͲð½âºóµÄ¹¹Ô캯Êý
+template<typename TyDst, typename TySrc>
+inline TyDst TupleCast(TySrc &&src)
+{
+ return _TupleCastAssist<TyDst>(std::forward<TySrc>(src), MakeIndexSequence<
+ std::tuple_size<typename std::remove_reference<TySrc>::type>::value>());
+}
+
+
+
+//tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐ͸¨ÖúÀàÐÍ
+template<typename TyFunc, typename TyTup, typename TyIdx>
+struct _TupleInvokeReturnTypeAssist
+{
+};
+template<typename TyFunc, typename TyTup, size_t ...c_idx_s>
+struct _TupleInvokeReturnTypeAssist<TyFunc, TyTup, IndexSequence<c_idx_s...>>
+{
+ using type = decltype(std::declval<TyFunc>()(std::get<c_idx_s>(std::declval<TyTup>())...));
+};
+//tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐÍ£¬Ê¹ÓôøcvrefµÄÀàÐÍ´«Èë
+template<typename TyFunc, typename TyTup>
+struct TupleInvokeReturnType
+{
+ using type = typename _TupleInvokeReturnTypeAssist<TyFunc, TyTup, MakeIndexSequence<
+ std::tuple_size<typename std::remove_reference<TyTup>::type>::value>>::type;
+};
+
+//tupleÀàÐ͵÷Óú¯Êý¸¨Öúº¯Êý
+template<typename TyFunc, typename TyTup, size_t ...c_idx_s>
+inline typename TupleInvokeReturnType<TyFunc &&, TyTup &&
+>::type _TupleInvokeAssist(TyFunc &&func, TyTup &&tup, IndexSequence<c_idx_s...>)
+{
+ return std::forward<TyFunc>(func)(std::get<c_idx_s>(std::forward<TyTup>(tup))...);
+}
+//tupleÀàÐ͵÷Óú¯Êý£¬±¾ÖÊÉÏÖ»ÒªÄܱ»getº¯Êý²ð½â¼´¿É£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë
+template<typename TyFunc, typename TyTup>
+inline typename TupleInvokeReturnType<TyFunc &&, TyTup &&
+>::type TupleInvoke(TyFunc &&func, TyTup &&tup)
+{
+ return _TupleInvokeAssist(std::forward<TyFunc>(func), std::forward<TyTup>(tup),
+ MakeIndexSequence<std::tuple_size<typename std::remove_reference<TyTup>::type>::value>());
+}
+
+
+
+//hashµ÷Óú¯Êý
+template<typename Ty>
+inline auto HashFunc(Ty &&arg)->
+decltype(std::hash<typename RemoveCVRef<Ty>::type>()(std::forward<Ty>(arg)))
+{
+ return std::hash<typename RemoveCVRef<Ty>::type>()(std::forward<Ty>(arg));
+}
+
+
+//hashµÄÌØÀý»¯
+namespace std
+{
+//¶ÔpairÌØÀý»¯£¬Ã»Óн»»»²»±äÐÔ£¬Óëtuple¼æÈÝ
+template<typename Ty1, typename Ty2>
+struct hash<std::pair<Ty1, Ty2>>
+{
+ typedef size_t result_type;
+ typedef std::pair<Ty1, Ty2> argument_type;
+ result_type operator()(const argument_type &pr) const
+ {
+ return HashFunc(HashFunc(pr.first))
+ ^ HashFunc(pr.second);
+ }
+};
+
+//¶ÔtupleÌØÀý»¯£¬Ã»Óн»»»²»±äÐÔ
+template<typename ...Tys>
+struct hash<std::tuple<Tys...>>
+{
+ typedef size_t result_type;
+ typedef std::tuple<Tys...> argument_type;
+ result_type operator()(const argument_type &tup) const
+ {
+ return Assist<sizeof...(Tys)>(tup);
+ }
+private:
+ template<size_t c_index>
+ static typename std::enable_if<c_index>=2, result_type
+ >::type Assist(const std::tuple<Tys...> &tup)
+ {
+ return HashFunc(Assist<c_index-1>(tup))
+ ^ HashFunc(std::get<c_index-1>(tup));
+ }
+ template<size_t c_index>
+ static typename std::enable_if<c_index==1, result_type
+ >::type Assist(const std::tuple<Tys...> &tup)
+ {
+ return HashFunc(std::get<0>(tup));
+ }
+ template<size_t c_index>
+ static typename std::enable_if<c_index==0, result_type
+ >::type Assist(const std::tuple<Tys...> &tup)
+ {
+ return 0;
+ }
+};
+}
+
+
+//¸÷Ààµü´úÆ÷hashÀ࣬βºóµü´úÆ÷½âÒýÓò»°²È«
+template<typename Ty>
+struct IteratorHash
+{
+ typedef size_t result_type;
+ typedef Ty argument_type;
+ result_type operator()(argument_type it) const
+ {
+ return std::hash<decltype(&*it)>()(&*it);
+ }
+};
+
+
+
+//¸÷Ààµü´úÆ÷±È½ÏÀ࣬βºóµü´úÆ÷½âÒýÓò»°²È«
+template<typename Ty>
+struct IteratorLess
+{
+ typedef bool result_type;
+ typedef Ty first_argument_type;
+ typedef Ty second_argument_type;
+ result_type operator()(const first_argument_type &it1,
+ const second_argument_type &it2) const
+ {
+ return &*it1<&*it2;
+ }
+};
+template<typename Ty>
+struct IteratorEuqalTo
+{
+ typedef bool result_type;
+ typedef Ty first_argument_type;
+ typedef Ty second_argument_type;
+ result_type operator()(const first_argument_type &it1,
+ const second_argument_type &it2) const
+ {
+ return &*it1==&*it2;
+ }
+};
+
+
+//¸÷Ààµü´úÆ÷½âÒýÓÃÖµ±È½ÏÀà
+template<typename Ty>
+struct IteratorDerefLess
+{
+ typedef bool result_type;
+ typedef Ty first_argument_type;
+ typedef Ty second_argument_type;
+ result_type operator()(const first_argument_type &it1,
+ const second_argument_type &it2) const
+ {
+ return *it1<*it2;
+ }
+};
+template<typename Ty>
+struct IteratorDerefEuqalTo
+{
+ typedef bool result_type;
+ typedef Ty first_argument_type;
+ typedef Ty second_argument_type;
+ result_type operator()(const first_argument_type &it1,
+ const second_argument_type &it2) const
+ {
+ return *it1==*it2;
+ }
+};
+
+
+
+//×Ö·ûÊý×ÖÅжÏ
+inline constexpr bool IsNumChar(char ch)
+{
+ return ch>='0' && ch<='9';
+}
+inline constexpr bool IsNotNumChar(char ch)
+{
+ return !IsNumChar(ch);
+}
+//×Ö·û´óд×ÖĸÅжÏ
+inline constexpr bool IsUppChar(char ch)
+{
+ return (ch>='A' && ch<='Z');
+}
+inline constexpr bool IsNotUppChar(char ch)
+{
+ return !IsUppChar(ch);
+}
+//×Ö·û´óд×ÖĸÅжÏ
+inline constexpr bool IsLowChar(char ch)
+{
+ return (ch>='a' && ch<='z');
+}
+inline constexpr bool IsNotLowChar(char ch)
+{
+ return !IsLowChar(ch);
+}
+//×Ö·û×ÖĸÅжÏ
+inline constexpr bool IsLetChar(char ch)
+{
+ return IsUppChar(ch) || IsLowChar(ch);
+}
+inline constexpr bool IsNotLetChar(char ch)
+{
+ return !IsLetChar(ch);
+}
+//×Ö·ûÊý×Ö×ÖĸÅжÏ
+inline constexpr bool IsNumLetChar(char ch)
+{
+ return IsNumChar(ch) || IsLetChar(ch);
+}
+inline constexpr bool IsNotNumLetChar(char ch)
+{
+ return !IsNumLetChar(ch);
+}
+//×Ö·û±êʶ·ûÅжÏ
+inline constexpr bool IsIdChar(char ch)
+{
+ return IsNumLetChar(ch) || (ch=='_');
+}
+inline constexpr bool IsNotIdChar(char ch)
+{
+ return !IsIdChar(ch);
+}
+//×Ö·ûÊ®Áù½øÖÆÅжÏ
+inline constexpr bool IsHexChar(char ch)
+{
+ return (ch>='0' && ch<='9')
+ || (ch>='a' && ch<='f') || (ch>='A' && ch<='F');
+}
+inline constexpr bool IsNotHexChar(char ch)
+{
+ return !IsHexChar(ch);
+}
+//×Ö·ûasciiÅжÏ
+inline constexpr bool IsAsciiChar(char ch)
+{
+ return ch>=0x00 && ch<=0x7F;
+}
+inline constexpr bool IsNotAsciiChar(char ch)
+{
+ return !IsAsciiChar(ch);
+}
+//×Ö·û¹ãÒå±êʶ·ûÅжÏ
+inline constexpr bool IsBroadIdChar(char ch)
+{
+ return IsIdChar(ch) || IsNotAsciiChar(ch);
+}
+inline constexpr bool IsNotBroadIdChar(char ch)
+{
+ return !IsBroadIdChar(ch);
+}
+//×Ö·û¿Õ°×·ûÅжÏ
+inline constexpr bool IsBlankChar(char ch)
+{
+ return ch==' ' || ch=='\t' || ch=='\r' || ch=='\n'
+ || ch=='\v' || ch=='\f';
+}
+inline constexpr bool IsNotBlankChar(char ch)
+{
+ return !IsBlankChar(ch);
+}
+
+
+//Сд×Öĸת»»´óд×Öĸ
+inline constexpr char LowCharToUppChar(char ch)
+{
+ return (char)
+ (IsLowChar(ch) ?
+ 'A'+(ch-'a')
+ :
+ ch);
+}
+//´óд×ÖĸתСд×Öĸ
+inline constexpr char UppCharToLowChar(char ch)
+{
+ return (char)
+ (IsUppChar(ch) ?
+ 'a'+(ch-'A')
+ :
+ ch);
+}
+
+
+//Êý×Ö×Ö·ûת»¯Êý×Ö
+inline constexpr int NumCharToNum(char ch)
+{
+ return IsNumChar(ch) ?
+ ch-'0'
+ :
+ -1;
+}
+//×Öĸ×Ö·ûת»¯Êý×Ö
+inline constexpr int LetCharToNum(char ch)
+{
+ return IsLowChar(ch) ?
+ ch-'a'
+ : IsUppChar(ch) ?
+ ch-'A'
+ :
+ -1;
+}
+//Ê®Áù½øÖÆ×Ö·ûת»¯Êý×Ö
+inline constexpr int HexCharToNum(char ch)
+{
+ return (ch>='0' && ch<='9') ?
+ ch-'0'
+ : (ch>='a' && ch<='f') ?
+ ch-'a'+10
+ : (ch>='A' && ch<='F') ?
+ ch-'A'+10
+ :
+ -1;
+}
+
+
+//Êý×Öת»¯Êý×Ö×Ö·û
+inline constexpr char NumToNumChar(int i)
+{
+ return (char)
+ ((i>=0 && i<=9) ?
+ i+'0'
+ :
+ 0);
+}
+//Êý×Öת»¯´óд×Öĸ×Ö·û
+inline constexpr char NumToUppChar(int i)
+{
+ return (char)
+ ((i>=0 && i<=25) ?
+ i+'A'
+ :
+ 0);
+}
+//Êý×Öת»¯Ð¡Ð´×Öĸ×Ö·û
+inline constexpr char NumToLowChar(int i)
+{
+ return (char)
+ ((i>=0 && i<=25) ?
+ i+'a'
+ :
+ 0);
+}
+//Êý×Öת»¯´óдʮÁù½øÖÆ×Ö·û
+inline constexpr char NumToUppHexChar(int i)
+{
+ return (char)
+ ((i>=0 && i<=9) ?
+ i+'0'
+ : (i>=10 && i<=15) ?
+ i+'A'
+ :
+ 0);
+}
+//Êý×Öת»¯Ð¡Ð´Ê®Áù½øÖÆ×Ö·û
+inline constexpr char NumToLowHexChar(int i)
+{
+ return (char)
+ ((i>=0 && i<=9) ?
+ i+'0'
+ : (i>=10 && i<=15) ?
+ i+'a'
+ :
+ 0);
+}
+