This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangshuo1-domain-classific…/TypeExtend.h

1281 lines
30 KiB
C
Raw Permalink Normal View History

#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);
}