diff options
| author | 张硕 <[email protected]> | 2019-12-31 11:11:28 +0800 |
|---|---|---|
| committer | 张硕 <[email protected]> | 2019-12-31 11:11:28 +0800 |
| commit | af96ee359d85fcb1c64dac645bc68199d39d0651 (patch) | |
| tree | bbc01d6c51de0ae94ed7cbf4ef6946acd8b222c0 | |
| parent | 6fe2e67322cbbbc849c68b930d1b1c1a00b27aec (diff) | |
Update IoOperator.h, makefile, StruAndAlgo.h, test.txt, TypeExtend.h, UsedMacro.h files
| -rw-r--r-- | IoOperator.h | 1606 | ||||
| -rw-r--r-- | StruAndAlgo.h | 2562 | ||||
| -rw-r--r-- | TypeExtend.h | 1280 | ||||
| -rw-r--r-- | UsedMacro.h | 166 | ||||
| -rw-r--r-- | makefile | 49 | ||||
| -rw-r--r-- | test.txt | 5 |
6 files changed, 5668 insertions, 0 deletions
diff --git a/IoOperator.h b/IoOperator.h new file mode 100644 index 0000000..e7e9fe6 --- /dev/null +++ b/IoOperator.h @@ -0,0 +1,1606 @@ +#pragma once + +//IO²Ù×÷¿â +//20191212-1034X + +#include <cstdint> +#include <cassert> + +#include <iostream> +#include <fstream> + +#include <limits> +#include <type_traits> +#include <algorithm> +#include <initializer_list> +#include <utility> +#include <tuple> +#include <iterator> + +#include <string> +#include <vector> +#include <array> +#include <deque> +#include <list> +#include <set> +#include <map> +#include <unordered_set> +#include <unordered_map> + +#include <exception> +#include <stdexcept> + +#include <mutex> + + +//¿â¹ØÁªÐèÇóÎļþ +#include "TypeExtend.h" + + + + +//°´¸ñʽ¶ÁȡһÐв¢·µ»Ø×Ö·û´® +inline bool _LineStringToInit(const std::string &strIn, std::string &strField, + std::string &strValue) +{ + //Èô"(\t1)abc(\t2)(\t3)def(\t4)(\t5)ghi\r\n" + //ÕÒÓÐЧ×Ö·ûÍ· + auto itSt = std::find_if_not(strIn.begin(), strIn.end(), IsBlankChar);//a + //ÅжϿջò×¢ÊÍ'#'';'"//" + if(itSt==strIn.end() || *itSt=='#' || *itSt==';' + ||(*itSt=='/' && itSt+1!=strIn.end() && itSt[1]=='/')) + return false; + //ÕÒ×Ö¶Î⣬²»ÒªÇóºóÐø + auto itGap = std::find_if(itSt+1, strIn.end(), IsBlankChar);//\t2 + strField.assign(itSt, itGap); + //ÕÒºóÐø´Ê + auto itWordSt = std::find_if_not(itGap, strIn.end(), IsBlankChar);//d + auto ritWordEd = std::find_if_not(strIn.rbegin(), + std::string::const_reverse_iterator(itWordSt), IsBlankChar);//i + //´æ´¢Öµ£¬¿ÉÄÜΪ¿Õ + if(itWordSt!=strIn.end() && itWordSt<ritWordEd.base()) + strValue.assign(itWordSt, ritWordEd.base()); + return true; +} + + + +//ÊäÈëÁ÷¶ÁÈ¡ÅäÖÃÎļþ£¬ÓÐÔ¤¶¨Òå×ֶη¶Î§£¬¶ÁÈ¡·¶Î§ÄÚµÄÖµ£¬·µ»ØÎ´ÕÒµ½µÄµÚÒ»¸ö×Ö¶Î +//ÅäÖÃÎļþ¸ñʽӦΪȥµô"#define"µÄºê¶¨Òå¸ñʽ£¬'#'';'"//"¶¼Îª×¢ÊÍ +//bReplaceÊÇ·ñͬһ×ֶκóÕßÌæ»»Ç°Õߣ¬ÈôÎªÖØ¸´¼¯ºÏÇÒΪ·ñÔòÖØ¸´Ìí¼Ó +//bCheckNullÊÇ·ñ¾Ü¾ø¶ÁȡֵΪ¿ÕµÄÇé¿ö +template<typename Ty1, typename Ty2> +inline Ty2 StreamReadPredefInit(std::istream &is, Ty1 &table, + Ty2 itFieldSt, Ty2 itFieldEd, bool bReplace= true, bool bCheckNull= true) +{ + //½«¹Ø¼ü×Ö¶ÎдÈë + Ty2 itField; + std::set<std::string> bstField; + for(itField=itFieldSt; itField!=itFieldEd; ++itField) { + bstField.emplace(*itField); + } + //´ÓÁ÷¶ÁÈ¡¹Ø¼ü×Ö¶Î + std::string strIn, strField, strValue; + while(std::getline(is, strIn)) { + //½âÎöÐдæÈë¶ÔÓ¦×Ö·û´® + if(!_LineStringToInit(strIn, strField, strValue)) + continue; + //ÅжÏÔÚ±íÖÐ + if(bstField.find(strField)==bstField.end()) + continue; + //ÅжÏֵΪ¿Õ + if(bCheckNull && strValue.empty()) + continue; + //Ìæ»»Ä£Ê½Ï + if(bReplace) { + auto itRes = table.find(strField); + if(itRes==table.end()) + table.emplace(std::move(strField), std::move(strValue)); + else + itRes->second = std::move(strValue); + } + //ÎÞ¶¯×÷ģʽÏ + else { + table.emplace(std::move(strField), std::move(strValue)); + } + } + //ÅжÏÌî³äÍê±Ï + for(itField=itFieldSt; itField!=itFieldEd; ++itField) { + std::string strTmp = *itField; + auto res = table.find(strTmp); + //ÈôûÕÒµ½×ֶλò¼ì²é¿ÕÇÒ×Ö¶Î¿Õ + if(res==table.end()) + break; + } + return itField; +} + + +//ÊäÈëÁ÷¶ÁÈ¡ÅäÖÃÎļþ£¬ÎÞÔ¤¶¨Òå×ֶη¶Î§£¬¶ÁÈ¡ËùÓÐÎļþµÄÖµ£¬·µ»Ø¶ÁÈ¡¸öÊý +//ÅäÖÃÎļþ¸ñʽӦΪȥµô"#define"µÄºê¶¨Òå¸ñʽ£¬'#'';'"//"¶¼Îª×¢ÊÍ +//bReplaceÊÇ·ñͬһ×ֶκóÕßÌæ»»Ç°Õߣ¬ÈôÎªÖØ¸´¼¯ºÏÇÒΪ·ñÔòÖØ¸´Ìí¼Ó +//bCheckNullÊÇ·ñ¾Ü¾ø¶ÁȡֵΪ¿ÕµÄÇé¿ö +template<typename Ty1> +inline int StreamReadAllInit(std::istream &is, Ty1 &table, + bool bReplace= true, bool bCheckNull= true) +{ + //´ÓÁ÷¶ÁÈ¡¹Ø¼ü×Ö¶Î + std::string strIn, strField, strValue; + while(std::getline(is, strIn)) { + //½âÎöÐдæÈë¶ÔÓ¦×Ö·û´® + if(!_LineStringToInit(strIn, strField, strValue)) + continue; + //ÅжÏֵΪ¿Õ + if(bCheckNull && strValue.empty()) + continue; + //Ìæ»»Ä£Ê½Ï + if(bReplace) { + auto itRes = table.find(strField); + if(itRes==table.end()) + table.emplace(std::move(strField), std::move(strValue)); + else + itRes->second = std::move(strValue); + } + //ÎÞ¶¯×÷ģʽÏ + else { + table.emplace(std::move(strField), std::move(strValue)); + } + } + return (int)table.size(); +} + + + +//ÊäÈëÁ÷¸¨Öúº¯Êý +//ʹÓÃflushË¢ÐÂÒ»ÐУ¬Ê¹ÓÃendsÇå¿Õ״̬£¬Ê¹ÓÃendlͬʱÍê³ÉˢкÍÇå¿Õ +inline bool operator >>(std::istream &is, + std::basic_ostream<char> &(*func)(std::basic_ostream<char> &)) +{ + bool res = (bool)is; + if(func==&std::flush<char, std::char_traits<char>>) + is.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); + else if(func==&std::ends<char, std::char_traits<char>>) + is.clear(); + else if(func==&std::endl<char, std::char_traits<char>>) { + is.clear(); + is.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); + } + else + assert(false); + return res; +} + + +////»ñÈ¡ÍêÕûÐÐ×÷Ϊ×Ö·û´®ÊäÈëÁ÷£¬Èç¹û»ñÈ¡ÍêisΪfailÔòÖ÷µ»ØÁ÷Ϊfail +//inline std::istringstream GetLineAsStream(std::istream &is, char gap= '\n') +//{ +// std::string strTmp; +// std::istringstream iss; +// if(!std::getline(is, strTmp, gap)) +// iss.setstate(std::ios_base::failbit); +// else +// iss.str(std::move(strTmp)); +// return std::move(iss); +//} + + + +//Êä³öÁ÷±£³ÖÀà +//ÓÃÓÚÔÚÊä³öºó¸½¼Ó¿ØÖƸñʽ£¬¶þ´ÎÊä³öÊ±ÕæÕýÊä³ö£¬ÐèÍâ²¿ÖØÔØÔËËã·û +template<typename Ty> +class OstreamHold +{ + OstreamHold() + = delete; +}; +//Êä³öÁ÷±£³ÖÀà×óÖµÒýÓÃÌØ»¯ +template<typename Ty> +class OstreamHold<Ty &> +{ +private: + std::ostream &os;//´æ´¢os + Ty &ref;//´æ´¢ÒýÓà +public: + //¹¹Ô캯Êý + explicit OstreamHold(std::ostream &o_os, Ty &o_ref): + os(o_os), ref(o_ref) + { + } + //ɾ³ý¿½±´ + OstreamHold(const OstreamHold<Ty &> &) + = delete; + OstreamHold<Ty &> &operator =(const OstreamHold<Ty &> &) + = delete; + //ĬÈÏÒÆ¶¯ + OstreamHold(OstreamHold<Ty &> &&) + = default; + OstreamHold<Ty &> &operator =(OstreamHold<Ty &> &&) + = default; + //Á÷ÒýÓà + std::ostream &operator()() const + { + return os; + } + //ÒýÓúͳÉÔ±ÒýÓà + Ty &operator *() const + { + return ref; + } + Ty *operator ->() const + { + return &ref; + } + //ת»»³£ÀàÐͰ汾 + operator OstreamHold<const Ty &>() const + { + return OstreamHold<const Ty &>(os, ref); + } +}; +//Êä³öÁ÷±£³ÖÀàÓÒÖµÒýÓÃÌØ»¯ +template<typename Ty> +class OstreamHold<Ty &&> +{ +private: + std::ostream &os;//´æ´¢os + Ty data;//´æ´¢ÒýÓà +public: + //¹¹Ô캯Êý + explicit OstreamHold(std::ostream &o_os, Ty &&o_data): + os(o_os), data(std::move(o_data)) + { + } + //ɾ³ý¿½±´ + OstreamHold(const OstreamHold<Ty &&> &) + = delete; + OstreamHold<Ty &&> &operator =(const OstreamHold<Ty &&> &) + = delete; + //ĬÈÏÒÆ¶¯ + OstreamHold(OstreamHold<Ty &&> &&) + = default; + OstreamHold<Ty &&> &operator =(OstreamHold<Ty &&> &&) + = default; + //ת»»×óÖµÁ÷ + OstreamHold<const Ty &> operator()() const + { + return OstreamHold<const Ty &>(os, data); + } + OstreamHold<Ty &> operator()() + { + return OstreamHold<Ty &>(os, data); + } + //ÒýÓúͳÉÔ±ÒýÓà + Ty &operator *() const + { + return data; + } + Ty *operator ->() const + { + return &data; + } +}; + + + +//Êä³öÁ÷¼¯ºÏÎÞËø±êÖ¾£¬×÷ΪÁ÷Êä³ö±íʾÎÞËø +class OstreamSetNoLock +{ +}; + +//Êä³öÁ÷¼¯ºÏÀà +//ÓÃÓÚ¶à¸öÊä³öÁ÷ͬʱÊä³ö£¬Ö§³Ö·ÇÁ÷ÒýÓ÷µ»ØÖµµÄ´«µÝÁ÷²Ù×÷ +//¸½¼Ó»¥³âËø¹¦Äܽӿڣ¬ÒªÇó²ÎÊý¿ÉËøÀàÐÍ£¬Í¬Ê±´ËÀàÒ²Âú×ã¿ÉËø +//ÈôÓÐËøÔòÁ÷²Ù×÷×Ô¶¯£¬³ý·Ç´«µÝ·ÇËø±êÖ¾£¬ÔÚÒ»´®Á÷²Ù×÷¿ªÊ¼½áÊøÊ±½øÐÐËø¶¨½âËø +template<typename TyMtx= std::mutex> +class OstreamSet +{ +public: + //Êä³ö¼¯ºÏ´«µÝÀàÐÍ + template<typename TyRes> + class Hold; + +public: + std::vector<std::ostream *> vecPOs;//Êä³öÁ÷£¬¸ü¸Ä·ÇḬ̈߳²È« + std::vector<TyMtx *> vecPMtx;//Ëø£¬¸ü¸Ä·ÇḬ̈߳²È« + +public: + //ĬÈϹ¹Ôì + OstreamSet() + = default; + //ɾ³ý¿½±´ + OstreamSet(const OstreamSet &) + = delete; + OstreamSet &operator =(const OstreamSet &) + = delete; + //ĬÈÏÒÆ¶¯£¬·ÇḬ̈߳²È« + OstreamSet(OstreamSet &&) + = default; + OstreamSet &operator =(OstreamSet &&) + = default; + //ÁÐ±í¹¹Ôì + explicit OstreamSet(std::initializer_list<std::ostream *> intlOs, + std::initializer_list<TyMtx *> intlMtx = {} + ): vecPOs(intlOs), vecPMtx(intlMtx) + { + } + //µü´úÆ÷¹¹Ôì + template<typename TyItOs, typename TyItMtx> + explicit OstreamSet(TyItOs itOsSt, TyItOs itOsEd, + TyItMtx itMtxSt, TyItMtx itMtxEd) + { + for(; itOsSt!=itOsEd; ++itOsSt) + vecPOs.push_back(&*itOsSt); + for(; itMtxSt!=itMtxEd; ++itMtxSt) + vecPMtx.push_back(&*itMtxSt); + } + template<typename TyItOs> + explicit OstreamSet(TyItOs itOsSt, TyItOs itOsEd): + OstreamSet(itOsSt, itOsEd, (TyMtx *)nullptr, (TyMtx *)nullptr) + { + } +public: + //ת·¢Á÷²Ù×÷£¬Ḭ̈߳²È«£¬°´Ë³Ðòµ÷ÓÃËø£¬Ðè±£Ö¤²»ËÀËø + template<typename Ty> + auto operator <<(Ty &&arg) const-> + Hold<decltype(*vecPOs.front()<<std::forward<Ty>(arg))> + { + //Á÷½á¹ûÀàÐÍÊý×é + using TyRes = decltype(*vecPOs.front()<<std::forward<Ty>(arg)); + std::vector<TypeHolder<TyRes>> vecRes; + vecRes.reserve(vecPOs.size()); + //µ÷ÓÃËø¶¨ + Lock(); + //Êä³ö²¢´æ´¢ + for(auto pOs : vecPOs) { + vecRes.emplace_back(*pOs <<std::forward<Ty>(arg)); + } + //Éú³É½á¹ûµÄHoldÀàÐÍ + return Hold<TyRes>(std::move(vecRes), vecPMtx.empty()? nullptr:this); + } + //¶Ô²Ù×÷·û½øÐÐת·¢ + template<int c_blank =0> + auto operator <<(std::ios_base &(*func)(std::ios_base &)) const-> + decltype(this->operator << <decltype((func))>(func)) + { + return operator << <decltype((func))>(func); + } + template<int c_blank =0> + auto operator <<(std::basic_ios<char> &(*func)(std::basic_ios<char> &)) const-> + decltype(this->operator << <decltype((func))>(func)) + { + return operator << <decltype((func))>(func); + } + template<int c_blank =0> + auto operator <<( + std::basic_ostream<char> &(*func)(std::basic_ostream<char> &)) const-> + decltype(this->operator << <decltype((func))>(func)) + { + return operator << <decltype((func))>(func); + } + //¶Ô²»Ëø±êÖ¾½øÐÐÁ÷²Ù×÷£¬Á÷Êä³ö½«²»½øÐÐËø¶¨ºÍ½âËø + Hold<std::ostream &> operator <<(OstreamSetNoLock) const + { + //Á÷½á¹ûÀàÐÍÊý×é + using TyRes = std::ostream &; + std::vector<TypeHolder<TyRes>> vecRes; + vecRes.reserve(vecPOs.size()); + //´æ´¢ÀàÐÍ + for(auto pOs : vecPOs) { + vecRes.emplace_back(*pOs); + } + //Éú³É½á¹ûµÄHoldÀàÐÍ + return Hold<TyRes>(std::move(vecRes), nullptr); + } + //µ÷ÓÃostreamµÄ³ÉÔ±º¯Êý£¬½øÐÐËø¶¨£¬ºöÂÔ·µ»ØÖµ + template<typename Ty, typename ...Tys> + void operator()(const Ty &pmf, Tys &&...args) const + { + //µ÷ÓÃËø¶¨ + Lock(); + //µ÷ÓóÉÔ±º¯Êý + for(auto pOs : vecPOs) { + (pOs->*pmf)(std::forward<Tys>(args)...); + } + //µ÷ÓýâËø + Unlock(); + } + //µ÷ÓÃËø¶¨ + void Lock() const + { + //˳Ðòµ÷ÓÃËø + for(auto pMtx : vecPMtx) + pMtx->lock(); + } + void lock() const + { + Lock(); + } + //µ÷ÓýâËø + void Unlock() const + { + //·´Ðò½âËø + for(auto rit =vecPMtx.rbegin(); rit!=vecPMtx.rend(); ++rit) + (*rit)->unlock(); + } + void unlock() const + { + Unlock(); + } + //³¢ÊÔËø¶¨ + bool TryLock() const + { + //˳Ðòµ÷Óó¢ÊÔËø + unsigned i; + for(i =0; i<vecPMtx.size(); ++i) { + if(!vecPMtx[i]->try_lock()) + break; + } + //³¢ÊÔʧ°ÜÔò½âËø + if(i!=vecPMtx.size()) { + for(--i; i>=0; --i) + vecPMtx[i]->unlock(); + return false; + } + else + return true; + } + bool try_lock() const + { + return TryLock(); + } +}; + +//Êä³öÁ÷¼¯ºÏ´«µÝÀàÐÍ +template<typename TyMtx> +template<typename TyRes> +class OstreamSet<TyMtx>::Hold +{ + friend class OstreamSet<TyMtx>; +private: + std::vector<TypeHolder<TyRes>> vecRes;//Êä³öÁ÷µÄ½á¹ûÊý×é + const OstreamSet<TyMtx> *pSet;//Êä³öÁ÷¼¯ºÏÖ¸Õ룬Îö¹¹½âËø±êÖ¾ + +private: + //¹¹Ô죬Êä³ö¼¯ºÏÒýÓóõʼ»¯ + explicit Hold(std::vector<TypeHolder<TyRes>> &&o_vecRes, + const OstreamSet<TyMtx> *o_pSet + ): vecRes(std::move(o_vecRes)), pSet(o_pSet) + { + } + //ɾ³ý¿½±´ + Hold(const Hold &) + = delete; + Hold &operator =(const Hold &) + = delete; + //ÒÆ¶¯²Ù×÷£¬ÒƳöÊý¾Ý²»ÐèÎö¹¹½âËø±êÖ¾ + Hold(Hold &&other) noexcept + { + this->operator =(std::move(other)); + } + Hold &operator =(Hold &&other) noexcept + { + if(this!=&other) { + vecRes = std::move(other.vecRes); + pSet = std::move(other.pSet); + other.pSet = nullptr; + } + return *this; + } +public: + //Îö¹¹º¯Êý£¬¸ù¾Ý±êÖ¾½øÐнâËø£¬·´Ðò½âËø + ~Hold() + { + if(pSet!=nullptr) { + //µ÷ÓýâËø + pSet->Unlock(); + } + } +public: + //ת·¢Á÷²Ù×÷£¬×ª·¢ºóÈ¥³ý½âËø±êÖ¾ + template<typename Ty> + auto operator <<(Ty &&arg)-> + Hold<decltype(vecRes.front().hold<<std::forward<Ty>(arg))> + { + //´Ë¶ÔÏó²»ÐèÎö¹¹½âËø + auto ptr = pSet; + pSet = nullptr; + //еÄÁ÷²Ù×÷½á¹ûÀàÐÍ + using TyResTmp = decltype(vecRes.front().hold<<std::forward<Ty>(arg)); + std::vector<TypeHolder<TyResTmp>> vecResTmp; + vecResTmp.reserve(vecRes.size()); + //Á÷Êä³ö²¢´æ´¢ + for(auto &refRes : vecRes) { + vecResTmp.emplace_back(refRes.hold <<std::forward<Ty>(arg)); + } + //¹¹ÔìеÄHoldÀàÐÍ£¬×ªÒåÎö¹¹½âËø±êÖ¾ + return Hold<TyResTmp>(std::move(vecResTmp), ptr); + } + //¶Ô²Ù×÷·û½øÐÐת·¢ + template<int c_blank =0> + auto operator <<(std::ios_base &(*func)(std::ios_base &))-> + decltype(this->operator << <decltype((func))>(func)) + { + return operator << <decltype((func))>(func); + } + template<int c_blank =0> + auto operator <<(std::basic_ios<char> &(*func)(std::basic_ios<char> &))-> + decltype(this->operator << <decltype((func))>(func)) + { + return operator << <decltype((func))>(func); + } + template<int c_blank =0> + auto operator <<( + std::basic_ostream<char> &(*func)(std::basic_ostream<char> &))-> + decltype(this->operator << <decltype((func))>(func)) + { + return operator << <decltype((func))>(func); + } +}; + + + +//¶ÏÑÔ²Ù×÷ÀàÊä³öÑ¡Ïî +enum class AssertOption +{ + thrw_log,//Å׳öÒì³£²¢Êä³öÈÕÖ¾ + thrw,//Å׳öÒì³£ + asst_log,//µ÷ÊÔ¶ÏÑÔ²¢Êä³öÈÕÖ¾ + asst,//µ÷ÊÔ¶ÏÑÔ + log,//Êä³öÈÕÖ¾ + none,//ÎÞ²Ù×÷ +}; + +//¶ÏÑÔ²Ù×÷Àà +template<typename TyOs= std::ostream> +class AssertOperator +{ +private: + //·Ç²¶»ñÒì³£ + class NoCatchError: + private std::runtime_error + { + //¼Ì³Ð»ùÀ๹Ô캯Êý£¨³ýĬÈÏ¿½±´¹¹Ô죩 + using std::runtime_error::runtime_error; + public: + //ĬÈϹ¹Ôì + NoCatchError(): + std::runtime_error("") + { + } + //ʹÓü̳Ðwhat + using std::runtime_error::what; + //Ê¡ÂԺϳÉ5¿½±´ + }; + +private: + TyOs &os;//Êä³öÀà +public: + AssertOption option;//Êä³öÑ¡Ïî + +public: + //¹¹Ôì + AssertOperator() = + delete; + explicit AssertOperator(TyOs &o_os, AssertOption o_option): + os(o_os), option(o_option) + { + } +public: + //Ö¸¶¨Ñ¡Ïî½øÐжÏÑÔ + bool operator()(AssertOption optionTmp, + bool bCond, const std::string &str= "") const + { + if(bCond) + return true; + //°´Ñ¡Ïî½øÐвÙ×÷ + if(optionTmp==AssertOption::thrw_log) { + os <<str <<std::flush; + throw NoCatchError(str); + } + else if(optionTmp==AssertOption::thrw) { + throw NoCatchError(str); + } + else if(optionTmp==AssertOption::asst_log) { + os <<str <<std::flush; + assert(false); + } + else if(optionTmp==AssertOption::asst) { + assert(false); + } + else if(optionTmp==AssertOption::log) { + os <<str <<std::flush; + } + else if(optionTmp==AssertOption::none) { + } + return false; + } + //ʹÓÃĬÈÏÑ¡Ïî½øÐжÏÑÔ + bool operator()(bool bCond, const std::string &str= "") const + { + return operator()(option, bCond, str); + } +}; + + + +//дÀàÐͶþ½øÖÆÎļþÀà +//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿ +class BinWriteFile +{ +public: + std::ofstream ofs;//ÎļþÁ÷ + +public: + //¹¹Ôì + BinWriteFile() + = default; + explicit BinWriteFile(const std::string &name, bool o_bAfter=false) + { + Open(name, o_bAfter); + } + //Îö¹¹ + ~BinWriteFile() + = default; + //ɾ³ý¿½±´ + BinWriteFile(const BinWriteFile &) + = delete; + BinWriteFile &operator =(BinWriteFile &) + = delete; + //ÒÆ¶¯¹¹Ôì + BinWriteFile(BinWriteFile &&file) + = default; + //ÒÆ¶¯¸³Öµ + BinWriteFile &operator =(BinWriteFile &&file) + = default; + +public: + //´ò¿ªÎļþ£¬o_bAfterÊÇ·ñ×·¼Óд + BinWriteFile &Open(const std::string &name, bool o_bAfter=false) + { + ofs.close(); + if(o_bAfter) + ofs.open(name, std::ios::binary|std::ios::app); + else + ofs.open(name, std::ios::binary); + if(!ofs.is_open()) + throw std::runtime_error("Can't Open Write File"); + return *this; + } + //¹Ø±ÕÎļþ + bool Close() + { + ofs.close(); + if(ofs.bad()) + throw std::runtime_error("Can't Close File"); + return true; + } + //·µ»Ø´ò¿ª×´Ì¬ + bool isopen() const + { + return ofs.is_open(); + } + //ÎļþÁ÷¿ÉÓã¬Ò»¶¨¿ÉÓà + bool IsFail() const + { + return !ofs.good(); + } + operator bool() const + { + return ofs.good(); + } + //Çå³ý´íÎó±êÖ¾ + void Clear() + { + ofs.clear(); + } + //Ë¢ÐÂÎļþ»º³åÇø + BinWriteFile &Fflush() + { + ofs.flush(); + return *this; + } + //ÖØ¶¨Î»Î»Öà + BinWriteFile &Seekp(std::ofstream::pos_type pos) + { + ofs.seekp(pos); + return *this; + } + BinWriteFile &Seekp(std::ofstream::off_type off, std::ios_base::seekdir dir) + { + ofs.seekp(off, dir); + return *this; + } + //²éѯλÖà + std::ofstream::pos_type Tellp() + { + return ofs.tellp(); + } + //¶Ô»º³åÇø½øÐÐÎļþдÈë + BinWriteFile &WriteBuf(const void *buf, size_t size) + { + ofs.write(reinterpret_cast<const char *>(buf), size); + if(ofs.bad()) + throw std::runtime_error("Can't Write File"); + return *this; + } + //¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ + template<typename Ty> + typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile & + >::Type WriteArray(const Ty *pt, size_t count) + { + WriteBuf(pt, sizeof(Ty)*count); + return *this; + } + //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ + template<typename Ty> + typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile & + >::Type WriteArray(const Ty *pt, size_t count) + { + for(; count!=0; --count, ++pt) + *this <<*pt; + return *this; + } +public: + //¶ÔÄÚÖÃÀàÐͽøÐÐÎļþдÈ룬°üÀ¨ÄÚÖÃÀàÐÍÊý×é + template<typename Ty> + typename std::enable_if<std::is_scalar< + typename std::remove_all_extents<Ty>::type>::value, BinWriteFile & + >::type operator <<(const Ty &r) + { + WriteBuf(&r, sizeof(r)); + return *this; + } + //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþдÈë + template<typename Ty, size_t N> + typename std::enable_if<!std::is_scalar< + typename std::remove_all_extents<Ty>::type>::value, BinWriteFile & + >::type operator <<(const Ty (&arrStr)[N]) + { + for(int64_t i=0; i<N; ++i) + *this <<arrStr[i]; + return *this; + } + //¶Ôpair½øÐÐÎļþдÈë + template<typename Ty1, typename Ty2> + BinWriteFile &operator <<(const std::pair<Ty1, Ty2> &pr) + { + *this <<pr.first <<pr.second; + return *this; + } + //¶Ôtuple½øÐÐÎļþдÈë + template<typename ...Tys> + BinWriteFile &operator <<(const std::tuple<Tys...> &tup) + { + TupleWrite<sizeof...(Tys)-1>(tup); + return *this; + } + template<int index, typename ...Tys> + typename std::enable_if<(index>=0), void + >::type TupleWrite(const std::tuple<Tys...> &tup) + { + *this <<std::get<index>(tup); + TupleWrite<index-1>(tup); + } + template<int index, typename Ty> + void TupleWrite(const Ty &tup) + { + } + //¶Ôstring½øÐÐÎļþдÈë + template<typename Ty> + BinWriteFile &operator <<(const std::basic_string<Ty> &str) + { + //д³ß´ç + int64_t size = str.size(); + operator <<(size); + //дÊý¾Ý + WriteBuf(&str[0], (size_t)(size*sizeof(Ty))); + return *this; + } + //¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþдÈë + template<typename Ty> + typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile & + >::type operator <<(const std::vector<Ty> &vec) + { + //д³ß´ç + int64_t size = vec.size(); + operator <<(size); + //дÊý¾Ý + WriteBuf(vec.data(), size*sizeof(Ty)); + return *this; + } + //¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë + template<typename Ty> + typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile & + >::type operator <<(const std::vector<Ty> &vec) + { + //д³ß´ç + int64_t size = vec.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : vec) + *this <<r; + return *this; + } + //¶ÔarrayÄÚÖÃÀàÐͽøÐÐÎļþдÈë + template<typename Ty, size_t c_size> + typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile & + >::type operator <<(const std::array<Ty, c_size> &arr) + { + //дÊý¾Ý + WriteBuf(arr.data(), c_size*sizeof(Ty)); + return *this; + } + //¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë + template<typename Ty, size_t c_size> + typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile & + >::type operator <<(const std::array<Ty, c_size> &arr) + { + //дÊý¾Ý + for(auto &r : arr) + *this <<r; + return *this; + } + //¶Ôdeque½øÐÐÎļþдÈë + template<typename Ty> + BinWriteFile &operator <<(const std::deque<Ty> &deq) + { + //д³ß´ç + int64_t size = deq.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : deq) + *this <<r; + return *this; + } + //¶Ôlist½øÐÐÎļþдÈë + template<typename Ty> + BinWriteFile &operator <<(const std::list<Ty> &lis) + { + //д³ß´ç + int64_t size = lis.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : lis) + *this <<r; + return *this; + } + //¶Ô¶þ²æÊ÷½øÐÐÎļþдÈë + template<typename Ty, typename TyComp> + BinWriteFile &operator <<(const std::set<Ty, TyComp> &bst) + { + //д³ß´ç + int64_t size = bst.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : bst) + *this <<r; + return *this; + } + //¶Ô¶àÖµ¶þ²æÊ÷½øÐÐÎļþдÈë + template<typename Ty, typename TyComp> + BinWriteFile &operator <<(const std::multiset<Ty, TyComp> &bst) + { + //д³ß´ç + int64_t size = bst.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : bst) + *this <<r; + return *this; + } + //¶Ô¶þ²æÊ÷¶Ô½øÐÐÎļþдÈë + template<typename Ty1, typename Ty2, typename TyComp> + BinWriteFile &operator <<(const std::map<Ty1, Ty2, TyComp> &bst) + { + //д³ß´ç + int64_t size = bst.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : bst) + *this <<r.first <<r.second; + return *this; + } + //¶Ô¶àÖµ¶þ²æÊ÷¶Ô½øÐÐÎļþдÈë + template<typename Ty1, typename Ty2, typename TyComp> + BinWriteFile &operator <<(const std::multimap<Ty1, Ty2, TyComp> &bst) + { + //д³ß´ç + int64_t size = bst.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : bst) + *this <<r.first <<r.second; + return *this; + } + //¶Ô¹þÏ£±í½øÐÐÎļþдÈë + template<typename Ty, typename TyHash, typename TyComp> + BinWriteFile &operator <<(const std::unordered_set<Ty, TyHash, TyComp> &htb) + { + //д³ß´ç + int64_t size = htb.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : htb) + *this <<r; + return *this; + } + //¶Ô¶àÖµ¹þÏ£±í½øÐÐÎļþдÈë + template<typename Ty, typename TyHash, typename TyComp> + BinWriteFile &operator <<(const std::unordered_multiset<Ty, TyHash, TyComp> &htb) + { + //д³ß´ç + int64_t size = htb.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : htb) + *this <<r; + return *this; + } + //¶Ô¹þÏ£±í¶Ô½øÐÐÎļþдÈë + template<typename Ty1, typename Ty2, typename TyHash, typename TyComp> + BinWriteFile &operator <<(const std::unordered_map<Ty1, Ty2, TyHash, TyComp> &htb) + { + //д³ß´ç + int64_t size = htb.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : htb) + *this <<r.first <<r.second; + return *this; + } + //¶Ô¶àÖµ¹þÏ£±í¶Ô½øÐÐÎļþдÈë + template<typename Ty1, typename Ty2, typename TyHash, typename TyComp> + BinWriteFile &operator <<(const std::unordered_multimap<Ty1, Ty2, TyHash, TyComp> &htb) + { + //д³ß´ç + int64_t size = htb.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : htb) + *this <<r.first <<r.second; + return *this; + } +}; + +//дÀàÐͶþ½øÖÆÎļþÀàµü´úÆ÷ +//ÊÇÊä³öµü´úÆ÷ +template<typename Ty> +class BinWriteFileIter: + public std::iterator<std::output_iterator_tag, void, + void, void, void> +{ +private://Êý¾Ý + BinWriteFile *pBwf;//¹ØÁªÎļþ + +public://»ù±¾º¯Êý + //ûÓÐĬÈϹ¹Ôì + BinWriteFileIter() + = delete; + //¹ØÁª¹¹Ôì + BinWriteFileIter(BinWriteFile &bwf): + pBwf(&bwf) + { + } +public://ÔËËã·ûÖØÔØ + //½âÒýÓòÙ×÷£¬·µ»Ø×ÔÉí + BinWriteFileIter &operator *() const + { + return *this; + } + //µÝÔö²Ù×÷£¬Ê²Ã´Ò²²»×ö£¬·µ»Ø×ÔÉí + BinWriteFileIter &operator ++() + { + return *this; + } + BinWriteFileIter &operator ++(int) + { + return *this; + } + //¸³Öµ²Ù×÷£¬½øÐÐÊä³ö + BinWriteFileIter &operator =(const Ty &data) + { + *pBwf <<data; + return *this; + } +}; + + +template<typename Ty> +class BinReadFileIter; +//¶ÁÀàÐͶþ½øÖÆÎļþÀà +//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿ +class BinReadFile +{ +public: + std::ifstream ifs;//ÎļþÁ÷ + bool bFast = false;//¿ìËÙģʽ£¬£¬Ò»´ÎÉêÇë×ã¹»Äڴ棬Êý×é¼Ç¼´íÎó¿ÉÄÜÔì³ÉÄÚ´æ²»×㣬¿ÉÔÚÈκÎʱºò¸ü¸Ä + bool bSave = false;//½ÚԼģʽ£¬ÉêÇëÄÚ´æÊ±²»ÉêÇë¶îÍâÁ¿£¬½ö¿ìËÙģʽÓ㬿ÉÔÚÈκÎʱºò¸ü¸Ä + static constexpr int64_t bufSize = 4096;//¶ÁÈ¡»º´æ´óС + +public: + //¹¹Ôì + explicit BinReadFile(bool o_bFast= false, bool o_bSave= false): + bFast(o_bFast), bSave(o_bSave) + { + } + //´ò¿ªÎļþ¹¹Ôì + template<typename Ty, typename= typename std::enable_if< + IsRemoveCVRefSameSzOrString<Ty>::value>::type + > explicit BinReadFile(Ty &&name, bool o_bFast= false, bool o_bSave= false): + bFast(o_bFast), bSave(o_bSave) + { + Open(std::forward<Ty>(name)); + } + //Îö¹¹ + ~BinReadFile() + = default; + //ɾ³ý¿½±´ + BinReadFile(const BinReadFile &) + = delete; + BinReadFile &operator =(BinReadFile &) + = delete; + //ÒÆ¶¯¹¹Ôì + BinReadFile(BinReadFile &&file) + = default; + //ÒÆ¶¯¸³Öµ + BinReadFile &operator =(BinReadFile &&file) + = default; + +public: + //´ò¿ªÎļþ + BinReadFile &Open(const std::string &name) + { + ifs.close(); + ifs.open(name, std::ios::binary); + if(ifs.bad()) + throw std::runtime_error("Open Read File Bad Error"); + return *this; + } + //¸²¸ÇCloseº¯Êý£¬Èô¼ì²â½áβÔò·µ»Ø¼ì²â½á¹û + bool Close(bool bTestEnd = false) + { + bool res = !bTestEnd; + //¼ì²â½áβ + if(bTestEnd) { + res = TestEof(); + } + ifs.close(); + if(ifs.bad()) + throw std::runtime_error("Can't Close File"); + return res; + } + //·µ»Ø´ò¿ª×´Ì¬ + bool IsOpen() const + { + return ifs.is_open(); + } + //ÎļþÁ÷¿ÉÓà + bool IsFail() const + { + return !ifs.good(); + } + operator bool() const + { + return ifs.good(); + } + //Çå³ý´íÎó±êÖ¾ + void Clear() + { + ifs.clear(); + } + //¼ì²â½á⣬»á½øÐÐÒ»´Î¶ÁÈ¡²Ù×÷ + bool TestEof() + { + ifs.get(); + if(ifs.bad()) + throw std::runtime_error("Read File Bad Error"); + return ifs.eof(); + } + //ÖØ¶¨Î»Î»Öà + BinReadFile &Seekg(std::ifstream::pos_type pos) + { + ifs.seekg(pos); + return *this; + } + BinReadFile &Seekg(std::ifstream::off_type off, std::ios_base::seekdir dir) + { + ifs.seekg(off, dir); + return *this; + } + //²éѯλÖà + std::ifstream::pos_type Tellg() + { + return ifs.tellg(); + } + //¶Ô»º³åÇø½øÐÐÎļþ¶ÁÈ¡ + BinReadFile &ReadBuf(void *buf, size_t size) + { + ifs.read(reinterpret_cast<char *>(buf), size); + if(ifs.bad()) + throw std::runtime_error("Read File Bad Error"); + return *this; + } + //¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ + template<typename Ty> + typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile & + >::Type ReadArray(Ty *pt, size_t count) + { + ReadBuf(pt, sizeof(Ty)*count); + return *this; + } + //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ + template<typename Ty> + typename std::enable_if<!std::is_scalar<Ty>::value, BinReadFile & + >::Type ReadArray(Ty *pt, size_t count) + { + for(; count!=0; --count, ++pt) { + if(ifs.fail()) + return; + *this >>*pt; + } + return *this; + } +public: + //¶ÔÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡£¬°üÀ¨ÄÚÖÃÀàÐÍÊý×é + template<typename Ty> + typename std::enable_if<std::is_scalar< + typename std::remove_all_extents<Ty>::type>::value, BinReadFile & + >::type operator >>(Ty &r) + { + ReadBuf(&r, sizeof(r)); + return *this; + } + //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþ¶ÁÈ¡ + template<typename Ty, size_t N> + typename std::enable_if<!std::is_scalar< + typename std::remove_all_extents<Ty>::type>::value, BinReadFile & + >::type operator >>(Ty (&arrStr)[N]) + { + for(int64_t i=0; i<N; ++i) { + if(ifs.fail()) + return *this; + *this >>arrStr[i]; + } + return *this; + } + //¶Ôpair½øÐÐÎļþ¶ÁÈ¡ + template<typename Ty1, typename Ty2> + BinReadFile &operator >>(std::pair<Ty1, Ty2> &pr) + { + *this >>pr.first >>pr.second; + return *this; + } + //¶Ôtuple½øÐÐÎļþ¶ÁÈ¡ + template<typename ...Tys> + BinReadFile &operator >>(std::tuple<Tys...> &tup) + { + TupleRead<sizeof...(Tys)-1>(tup); + return *this; + } + template<int index, typename ...Tys> + typename std::enable_if<(index>=0), void + >::type TupleRead(std::tuple<Tys...> &tup) + { + *this >>std::get<index>(tup); + TupleRead<index-1>(tup); + } + template<int index, typename Ty> + void TupleRead(Ty &tup) + { + } + //¶Ôstring½øÐÐÎļþ¶ÁÈ¡ + template<typename Ty> + BinReadFile &operator >>(std::basic_string<Ty> &str) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + str.clear(); + //¶ÁÊý¾Ý + if(bFast) { + if(bSave) + str.reserve((typename std::basic_string<Ty>::size_type)size); + str.resize((typename std::basic_string<Ty>::size_type)size); + ReadBuf(&str[0], (size_t)(size*sizeof(Ty))); + } + else { + constexpr int64_t perBufSize = bufSize/sizeof(Ty); + for(; size>0; size-=perBufSize) { + if(ifs.fail()) + return *this; + int64_t realSize = size<perBufSize? size:perBufSize; + auto nowSize = str.size(); + str.resize((typename std::basic_string<Ty>::size_type)(nowSize+realSize)); + ReadBuf(&str[0]+nowSize, (size_t)(realSize*sizeof(Ty))); + } + } + return *this; + } + //¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ + template<typename Ty> + typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile & + >::type operator >>(std::vector<Ty> &vec) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + constexpr int64_t perBufSize = bufSize/sizeof(Ty); + vec.clear(); + //¶ÁÊý¾Ý + if(bFast) { + if(bSave) + vec.reserve((typename std::vector<Ty>::size_type)size); + vec.resize((typename std::vector<Ty>::size_type)size); + ReadBuf(vec.data(), size*sizeof(Ty)); + } + else { + for(; size>0; size-=perBufSize) { + if(ifs.fail()) + return *this; + int64_t realSize = size<perBufSize? size:perBufSize; + auto nowSize = vec.size(); + vec.resize((typename std::vector<Ty>::size_type)(nowSize+realSize)); + ReadBuf(vec.data()+nowSize, realSize*sizeof(Ty)); + } + } + return *this; + } + //¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý + template<typename Ty> + typename std::enable_if<!std::is_scalar<Ty>::value, BinReadFile & + >::type operator >>(std::vector<Ty> &vec) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + //¶ÁÊý¾Ý + vec.clear(); + if(bFast) { + if(bSave) + vec.reserve((typename std::vector<Ty>::size_type)size); + vec.resize((typename std::vector<Ty>::size_type)size); + for(auto &r : vec) { + if(ifs.fail()) + return *this; + *this >>r; + } + } + else { + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + vec.emplace_back(); + *this >>vec.back(); + } + } + return *this; + } + //¶ÔarrayÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ + template<typename Ty, size_t c_size> + typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile & + >::type operator >>(std::array<Ty, c_size> &arr) + { + //¶ÁÊý¾Ý + ReadBuf(arr.data(), c_size*sizeof(Ty)); + return *this; + } + //¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ + template<typename Ty, size_t c_size> + typename std::enable_if<!std::is_scalar<Ty>::value, BinReadFile & + >::type operator >>(std::array<Ty, c_size> &arr) + { + //¶ÁÊý¾Ý + for(auto &ele: arr) { + if(ifs.fail()) + return *this; + *this >>ele; + } + return *this; + } + //¶Ôdeque½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý + template<typename Ty> + BinReadFile &operator >>(std::deque<Ty> &deq) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + deq.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + deq.emplace_back(); + *this >>deq.back(); + } + return *this; + } + //¶Ôlist½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý + template<typename Ty> + BinReadFile &operator >>(std::list<Ty> &lis) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + lis.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + lis.emplace_back(); + *this >>lis.back(); + } + return *this; + } + //¶Ô¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template<typename Ty, typename TyComp> + BinReadFile &operator >>(std::set<Ty, TyComp> &bst) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + bst.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + Ty data; + *this >>data; + bst.insert(bst.end(), std::move(data)); + } + return *this; + } + //¶Ô¶àÖµ¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template<typename Ty, typename TyComp> + BinReadFile &operator >>(std::multiset<Ty, TyComp> &bst) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + bst.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + Ty data; + *this >>data; + bst.insert(bst.end(), std::move(data)); + } + return *this; + } + //¶Ô¶þ²æÊ÷¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template<typename Ty1, typename Ty2, typename TyComp> + BinReadFile &operator >>(std::map<Ty1, Ty2, TyComp> &bst) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + bst.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + Ty1 data; + *this >>data; + if(ifs.fail()) + return *this; + auto res = bst.emplace_hint(bst.end(), std::piecewise_construct, + std::forward_as_tuple(std::move(data)), std::make_tuple()); + *this >>res->second; + } + return *this; + } + //¶Ô¶àÖµ¶þ²æÊ÷¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template<typename Ty1, typename Ty2, typename TyComp> + BinReadFile &operator >>(std::multimap<Ty1, Ty2, TyComp> &bst) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + bst.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + Ty1 data; + *this >>data; + if(ifs.fail()) + return *this; + auto res = bst.emplace_hint(bst.end(), std::piecewise_construct, + std::forward_as_tuple(std::move(data)), std::make_tuple()); + *this >>res->second; + } + return *this; + } + //¶Ô¹þÏ£±í½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template<typename Ty, typename TyHash, typename TyComp> + BinReadFile &operator >>(std::unordered_set<Ty, TyHash, TyComp> &htb) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + htb.clear(); + //¶ÁÊý¾Ý + if(bFast) + htb.reserve((typename std::unordered_set<Ty, TyHash, TyComp>::size_type)size); + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + Ty data; + *this >>data; + htb.insert(std::move(data)); + } + return *this; + } + //¶Ô¶àÖµ¹þÏ£±í½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template<typename Ty, typename TyHash, typename TyComp> + BinReadFile &operator >>(std::unordered_multiset<Ty, TyHash, TyComp> &htb) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + htb.clear(); + //¶ÁÊý¾Ý + if(bFast) + htb.reserve((typename std::unordered_multiset<Ty, TyHash, TyComp>::size_type)size); + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + Ty data; + *this >>data; + htb.insert(std::move(data)); + } + return *this; + } + //¶Ô¹þÏ£±í¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template<typename Ty1, typename Ty2, typename TyHash, typename TyComp> + BinReadFile &operator >>(std::unordered_map<Ty1, Ty2, TyHash, TyComp> &htb) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + htb.clear(); + //¶ÁÊý¾Ý + if(bFast) + htb.reserve((typename std::unordered_map<Ty1, Ty2, TyHash, TyComp>::size_type)size); + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + Ty1 data; + *this >>data; + if(ifs.fail()) + return *this; + auto res = htb.emplace(std::piecewise_construct, + std::forward_as_tuple(std::move(data)), std::make_tuple()).first; + *this >>res->second; + } + return *this; + } + //¶Ô¶àÖµ¹þÏ£±í¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template<typename Ty1, typename Ty2, typename TyHash, typename TyComp> + BinReadFile &operator >>(std::unordered_multimap<Ty1, Ty2, TyHash, TyComp> &htb) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + htb.clear(); + //¶ÁÊý¾Ý + if(bFast) + htb.reserve((typename std::unordered_multimap<Ty1, Ty2, TyHash, TyComp>::size_type)size); + for(int64_t i=0; i<size; ++i) { + if(ifs.fail()) + return *this; + Ty1 data; + *this >>data; + if(ifs.fail()) + return *this; + auto res = htb.emplace(std::piecewise_construct, + std::forward_as_tuple(std::move(data)), std::make_tuple()); + *this >>res->second; + } + return *this; + } +}; + +//¶ÁÀàÐͶþ½øÖÆÎļþÀàµü´úÆ÷ +//ÊÇÊäÈëµü´úÆ÷£¬´æ´¢ÀàÐͱØÐë¿ÉĬÈϹ¹Ôì +template<typename Ty> +class BinReadFileIter: + public std::iterator<std::input_iterator_tag, Ty, + int64_t, Ty *, Ty &> +{ +private://Êý¾Ý + BinReadFile *pBrf;//¹ØÁªÎļþ + int64_t size;//Ê£ÓàдÈë´óС£¬¸ºÊý±íʾÎÞÏÞдÈë + Ty data;//´æ´¢Êý¾Ý + +public://»ù±¾º¯Êý + //ĬÈϹ¹Ô죬³ÉΪβºóµü´úÆ÷ + BinReadFileIter(): + pBrf(nullptr), size(0) + { + } + //¹ØÁª¹¹Ô죬³õʼ½øÐжÁÈ¡£¬¿ÉÑ¡ÔñµÄ¼ÓÈë¶ÁÈ¡ÊýÁ¿ÏÞÖÆ + BinReadFileIter(BinReadFile &brf, int64_t o_size= -1): + pBrf(&brf), size(o_size) + { + Read(); + } +public://ÔËËã·ûÖØÔØ + //½âÒýÓòÙ×÷£¬·µ»ØÊý¾ÝÒýÓã¬Ö§³ÖÒÆ¶¯²Ù×÷ + Ty &operator *() const + { + return data; + } + Ty *operator ->() const + { + return &operator *(); + } + //µÝÔö²Ù×÷£¬Í¬Ê±½øÐжÁÈ¡ + BinReadFileIter &operator ++() + { + Read(); + return *this; + } + BinReadFileIter operator ++(int) + { + BinReadFileIter ret(*this); + operator ++(); + return ret; + } + //±È½Ï²Ù×÷£¬Ö¸ÏòÏàͬµÄÎļþ¾ÍÈÏΪÏàͬ + bool operator ==(const BinReadFileIter &other) const + { + return pBrf==other.pBrf; + } + bool operator !=(const BinReadFileIter &other) const + { + return !operator ==(other); + } +private: + //¶ÁÈ¡Êý¾Ý£¬Ã¿´Î¶ÁÈ¡ÊÇÎö¹¹ÔÙĬÈϹ¹ÔìÒ»´ÎÊý¾Ý£¬ÒÔÖ§³ÖÒÆ¶¯²Ù×÷ + void Read() + { + assert(pBrf!=nullptr); + //ÈôÊ£Óà0ÔòתΪβºó + if(size==0) { + pBrf = nullptr; + return; + } + //Çå³ý + CallDestruct(data); + new(&data) Ty(); + //¶ÁÈ¡ + *pBrf >>data; + //Èô¶Áȡʧ°ÜÔòתΪβºó + if(!*pBrf) + pBrf = nullptr; + //¼õÉÙÊ£Óà + if(size>0) + -- size; + } +}; diff --git a/StruAndAlgo.h b/StruAndAlgo.h new file mode 100644 index 0000000..f4d8113 --- /dev/null +++ b/StruAndAlgo.h @@ -0,0 +1,2562 @@ +#pragma once + +//Êý¾Ý½á¹¹ºÍËã·¨À©³ä +//20191212-2054 + +#include <cstddef> +#include <cmath> +#include <cassert> + +#include <type_traits> +#include <limits> +#include <algorithm> +#include <initializer_list> +#include <utility> +#include <tuple> +#include <functional> +#include <iterator> + +#include <string> +#include <vector> +#include <list> +#include <map> +#include <unordered_map> + +#include <stdexcept> +#include <random> +#include <ratio> + + +//¿â¹ØÁªÐèÇóÎļþ +#include "TypeExtend.h" + + + +//ÆäËû¿âÎļþÉùÃ÷ + +//tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐÍ£¬Ê¹ÓôøcvrefµÄÀàÐÍ´«Èë +template<typename TyFunc, typename TyTup> +struct TupleInvokeReturnType; + +//tupleÀàÐ͵÷Óú¯Êý£¬±¾ÖÊÉÏÖ»ÒªÄܱ»getº¯Êý²ð½â¼´¿É£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë +template<typename TyFunc, typename TyTup> +inline typename TupleInvokeReturnType<TyFunc &&, TyTup && +>::type TupleInvoke(TyFunc &&func, TyTup &&tup); + +//дÀàÐͶþ½øÖÆÎļþÀà +//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿ +class BinWriteFile; + +//¶ÁÀàÐͶþ½øÖÆÎļþÀà +//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿ +class BinReadFile; + + + + +//¿ìËÙ¼ÆËãÃݴΣ¬×¢Òâ·µ»ØÀàÐͺͻùÀàÐÍÏàͬ +template<typename Ty> +inline constexpr Ty FastPower(Ty base, int power) +{ + return power<0 ? 0 + : power==0 ? 1 + : (power&1)==0 ? FastPower(base*base, power>>1) + : base*FastPower(base*base, power>>1); +} + + + +//ÍÆËã±ÈÀý±íʾ¾«¶È£¬¼´±ÈÀýÀ©´óµ×ÊýµÄ¼¸´ÎÃÝ¿ÉÒÔ´óÓÚµÈÓÚ»ù×¼±ÈÀý +template<typename Ratio, typename BaseRatio, + typename CompareRatio =std::ratio<1> +> inline constexpr typename std::enable_if< + std::ratio_greater_equal<Ratio, CompareRatio>::value, int +>::type RatioPrecision() +{ + return 0; +} +template<typename Ratio, typename BaseRatio, + typename CompareRatio =std::ratio<1> +> inline constexpr typename std::enable_if< + !std::ratio_greater_equal<Ratio, CompareRatio>::value, int +>::type RatioPrecision() +{ + return RatioPrecision<std::ratio_multiply<Ratio, BaseRatio>, + BaseRatio, CompareRatio>()+1; +} + + + +//Éú³ÉºóÒ»¸ö×éºÏÊý£¬·µ»ØÊÇ·ñµ½Í· +//ÒªÇóË«Ïòµü´úÆ÷£¬¿ÉµÝÔö¡¢ÏàµÈ±È½ÏÖµÀàÐÍ +template<typename TyIt, typename Ty> +bool NextCombination(TyIt st, TyIt ed, Ty rangeSt, Ty rangeEd) +{ + auto it= ed, it1= it; + //ÕÒÊýÖµ¿Õ϶ + for(; it!=st; --it) { + it1 = it; + -- it1; + if(it==ed) { + if(!(*it1==rangeEd)) { + ++ *it1; + break; + } + } + else { + auto value = *it1; + ++ value; + if(!(value==*it)) { + *it1 = value; + break; + } + } + } + //ºóÐø×éºÏÊýµÝÔö + bool res = it!=st; + if(it!=ed) { + if(!res) + *it = rangeSt; + else { + it1 = it; + -- it1; + *it = *it1; + ++ *it; + } + for(it1=it, ++it; it!=ed; it1=it, ++it) { + *it = *it1; + ++ *it; + } + } + return res; +} + +//Éú³ÉºóÒ»¸öÅÅÁÐ×éºÏÊý£¬·µ»ØÊÇ·ñµ½Í· +//ÒªÇóË«Ïòµü´úÆ÷£¬¿ÉµÝÔö¡¢ÏàµÈ±È½ÏÖµÀàÐÍ +template<typename TyIt, typename Ty> +bool NextCombinationPermutation(TyIt st, TyIt ed, Ty rangeSt, Ty rangeEd) +{ + if(!std::next_permutation(st, ed)) { + if(!NextCombination(st, ed, rangeSt, rangeEd)) + return false; + } + return true; +} + + + +//¼ÆÊý¼¯ºÏ½»¼¯£¬ÏßÐÔ¸´ÔÓ¶È£¬ÒªÇóÒÑÅÅÐò +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 size_t SetIntersectionCount(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, + TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) +{ + size_t ret = 0; + while(true) { + if(st1==ed1 || st2==ed2) + break; + //Á½Õß¶¼ÓÐ + if(funcEqual(*st1, *st2)) { + ++st1, ++st2; + ++ ret; + } + //ǰÕßÓУ¬ºóÕßûÓÐ + else if(funcLess(*st1, *st2)) { + ++ st1; + } + //ºóÕßÓУ¬Ç°ÕßûÓÐ + else { + ++ st2; + } + } + return ret; +} + +//¼ÆÊý¼¯ºÏ²¢¼¯£¬ÏßÐÔ¸´ÔÓ¶È£¬ÒªÇóÒÑÅÅÐò +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 size_t SetUnionCount(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, + TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) +{ + size_t ret = 0; + while(true) { + if(st1==ed1 || st2==ed2) { + //ºóÕßÓÐÊ£Óà + if(st1==ed1) + ret += std::distance(st2, ed2); + //ǰÕßÓÐÊ£Óà + else + ret += std::distance(st1, ed1); + break; + } + //Á½Õß¶¼ÓÐ + if(funcEqual(*st1, *st2)) { + ++st1, ++st2; + ++ ret; + } + //ǰÕßÓУ¬ºóÕßûÓÐ + else if(funcLess(*st1, *st2)) { + ++ st1; + ++ ret; + } + //ºóÕßÓУ¬Ç°ÕßûÓÐ + else { + ++ st2; + ++ ret; + } + } + return ret; +} + +//¼ÆÊý¼¯ºÏ²î¼¯£¬ÏßÐÔ¸´ÔÓ¶È£¬ÒªÇóÒÑÅÅÐò +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 size_t SetDifferenceCount(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, + TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) +{ + size_t ret = 0; + while(true) { + if(st1==ed1 || st2==ed2) { + //ºóÕßÓÐÊ£Óà + if(st1==ed1) + ; + //ǰÕßÓÐÊ£Óà + else + ret += std::distance(st1, ed1); + break; + } + //Á½Õß¶¼ÓÐ + if(funcEqual(*st1, *st2)) { + ++st1, ++st2; + } + //ǰÕßÓУ¬ºóÕßûÓÐ + else if(funcLess(*st1, *st2)) { + ++ st1; + ++ ret; + } + //ºóÕßÓУ¬Ç°ÕßûÓÐ + else { + ++ st2; + } + } + return ret; +} + +//¼ÆÊý¼¯ºÏ¶Ô³Æ²î¼¯£¬ÏßÐÔ¸´ÔÓ¶È£¬ÒªÇóÒÑÅÅÐò +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 size_t SetSymmetricDifferenceCount(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, + TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) +{ + size_t ret = 0; + while(true) { + if(st1==ed1 || st2==ed2) { + //ºóÕßÓÐÊ£Óà + if(st1==ed1) + ret += std::distance(st2, ed2); + //ǰÕßÓÐÊ£Óà + else + ret += std::distance(st1, ed1); + break; + } + //Á½Õß¶¼ÓÐ + if(funcEqual(*st1, *st2)) { + ++st1, ++st2; + } + //ǰÕßÓУ¬ºóÕßûÓÐ + else if(funcLess(*st1, *st2)) { + ++ st1; + ++ ret; + } + //ºóÕßÓУ¬Ç°ÕßûÓÐ + else { + ++ st2; + ++ ret; + } + } + return ret; +} + + + + +//²¢²é¼¯£¬Êý×ÖË÷Òý£¬Êý×é½á¹¹£¬¿ÉÒÔΪ¿ÕÀàÐÍ +template<typename TyData= void> +class IndexDisjointSet +{ +private: + //²¢²é¼¯½ÚµãÊý¾Ý½á¹¹ + struct Node: + public ValueHolder<TyData> + { + size_t idxPr;//¸¸Ö¸Õë + size_t rank = 0;//ÖÈ£¬Ëã·¨Óà + template<typename ...Ty_S> + Node(size_t idx, Ty_S &&...arg_s): + ValueHolder<TyData>(std::forward<Ty_S>(arg_s)...), idxPr(idx) + { + } + }; + +private: + std::vector<Node> vec;//Êý¾Ý + +public: + //¹¹Ô캯Êý + IndexDisjointSet() + = default; + IndexDisjointSet(const IndexDisjointSet &) + = default; + IndexDisjointSet &operator =(const IndexDisjointSet &) + = default; + IndexDisjointSet(IndexDisjointSet &&) + = default; + IndexDisjointSet &operator =(IndexDisjointSet &&) + = default; + //¶àÊý¾Ý¹¹Ôì + template<typename ...Ty_S> + explicit IndexDisjointSet(size_t size, Ty_S &&...arg_s) + { + Assign(size, std::forward<Ty_S>(arg_s)...); + } +public: + //¶àÊý¾Ý¸³Öµ + template<typename ...Ty_S> + IndexDisjointSet &Assign(size_t size, Ty_S &&...arg_s) + { + for(size_t i=0; i!=size; ++i) + Emplace(std::forward<Ty_S>(arg_s)...); + return *this; + } + //»ñÈ¡Êý¾Ý + typename Node::RefType operator[](size_t idx) + { + return vec[idx]; + } + typename Node::ConstRefType operator[](size_t idx) const + { + return vec[idx]; + } + //»ñÈ¡´óС + size_t Size() const + { + return vec.size(); + } + //Çå¿Õ + void Clear() + { + vec.clear(); + } + //Ìí¼Óµã£¬·µ»Ø¸ù + template<typename ...Ty_S> + size_t Emplace(Ty_S &&...arg_s) + { + size_t root = vec.size(); + vec.emplace_back(root, std::forward<Ty_S>(arg_s)...); + return root; + } + //Ìí¼ÓµãͬʱÁ¬½Ó£¬·µ»Ø¸ù + template<typename ...Ty_S> + size_t EmplaceUnion(size_t idx, Ty_S &&...arg_s) + { + size_t root = vec.size(); + vec.emplace_back(root, std::forward<Ty_S>(arg_s)...); + return Union(root, idx); + } + //ÕÒ¸ù½Úµã + size_t FindRoot(size_t idx) + { + if(vec[idx].idxPr!=idx) + //ÕÒµÄͬʱÁ¬½Óµ½¸ù + vec[idx].idxPr = FindRoot(vec[idx].idxPr); + return vec[idx].idxPr; + } + //ºÏ²¢¼¯ºÏ£¬·µ»Ø¸ù + size_t Union(size_t idx1, size_t idx2) + { + size_t root1 = FindRoot(idx1), root2 = FindRoot(idx2); + if(vec[root1].rank<=vec[root2].rank) { + //1Á¬µ½2ÉÏ + vec[root1].idxPr = root2; + if(vec[root1].rank==vec[root2].rank) + ++ vec[root2].rank; + return root2; + } + else { + //2Á¬µ½1ÉÏ + vec[root2].idxPr = root1; + return root1; + } + } + //ÈÝÆ÷½Ó¿Ú + void Reserve(size_t size) + { + vec.reserve(size); + } + size_t Capacity() const + { + return vec.capacity(); + } + void ShinkToFit() + { + return vec.shink_to_fit(); + } +}; + + +template<typename TyKey, typename TyValue= void, typename TyCom= std::less<TyKey>> +class MapDisjointSetNode; +//Ê÷Ðβ¢²é¼¯ÀàÐͼòд£¬Ö§³ÖÁ¬½ÓºÍÌí¼Ó»ìÓ㬲¢²é¼¯±êǩΪÊ÷µü´úÆ÷ +template<typename TyKey, typename TyValue= void, typename TyCom= std::less<TyKey>> +using MapDisjointSet = std::map<TyKey, MapDisjointSetNode<TyKey, TyValue, TyCom>, TyCom>; +//Ê÷Ðβ¢²é¼¯£¬½Úµã½á¹¹£¬½«Æä¸³¸ømapÄ£°åÀàÐÍʹÓà +template<typename TyKey, typename TyValue, typename TyCom> +class MapDisjointSetNode: + private ValueHolder<TyValue> +{ + template<typename TyIt> + friend TyIt MapDisjointSetFindRoot(TyIt it); + template<typename TyIt> + friend TyIt MapDisjointSetUnion(TyIt it1, TyIt it2); +private: + typename MapDisjointSet<TyKey, TyValue, TyCom>::iterator itPr;//´æ´¢Ö¸Õë + size_t rank = 0;//ÖÈ£¬Ëã·¨Óà + bool bRoot = true;//¼Ç¼ÊÇ·ñΪ¸ù£¬Îª¸ùʱ²»Ðè±£Ö¤Ö¸ÕëÓÐЧ +public: + //¹¹Ô캯Êý + template<typename ...Ty_S> + MapDisjointSetNode(Ty_S &&...arg_s): + ValueHolder<TyValue>(std::forward<Ty_S>(arg_s)...) + { + } + //ÒýÓÃÔʼÊý¾Ý + typename ValueHolder<TyValue>::RefType Get() + { + return this->hold; + } + typename ValueHolder<TyValue>::ConstRefType Get() const + { + return this->hold; + } +}; +//Ê÷Ðβ¢²é¼¯¾²Ì¬Ëã·¨£¬ÕÒ¸ù½Úµã£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷ +template<typename TyIt> +inline TyIt MapDisjointSetFindRoot(TyIt it) +{ + if(it->second.bRoot) + return it; + else { + it->second.itPr = MapDisjointSetFindRoot(it->second.itPr); + return it->second.itPr; + } +} +//Ê÷Ðβ¢²é¼¯¾²Ì¬Ëã·¨£¬ºÏ²¢¼¯ºÏ£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷£¬·µ»Ø¸ù +template<typename TyIt> +inline TyIt MapDisjointSetUnion(TyIt it1, TyIt it2) +{ + TyIt root1= MapDisjointSetFindRoot(it1), root2= MapDisjointSetFindRoot(it2); + if(root1==root2) + return root1; + if(root1->second.rank<=root2->second.rank) { + //1Á¬µ½2ÉÏ + root1->second.itPr = root2; + root1->second.bRoot = false; + if(root1->second.rank==root2->second.rank) + ++ root2->second.rank; + return root2; + } + else { + //2Á¬µ½1ÉÏ + root2->second.itPr = root1; + root2->second.bRoot = false; + return root1; + } +} + + +template<typename TyKey, typename TyValue= void, + typename TyHash= std::hash<TyKey>, typename TyEqual= std::equal_to<TyKey> +> class UnordMapDisjointSetNode; +//¹þÏ£²¢²é¼¯ÀàÐͼòд£¬Ö§³ÖÁ¬½ÓºÍÌí¼Ó»ìÓ㬲¢²é¼¯±êǩΪÄÚÈÝpairÖ¸Õë +template<typename TyKey, typename TyValue= void, + typename TyHash= std::hash<TyKey>, typename TyEqual= std::equal_to<TyKey> +> using UnordMapDisjointSet = std::unordered_map<TyKey, + UnordMapDisjointSetNode<TyKey, TyValue, TyHash, TyEqual>, TyHash, TyEqual>; +//¹þÏ£²¢²é¼¯£¬½Úµã½á¹¹£¬½«Æä¸³¸øunordered_mapÄ£°åÀàÐÍʹÓà +template<typename TyKey, typename TyValue, typename TyHash, typename TyEqual> +class UnordMapDisjointSetNode: + private ValueHolder<TyValue> +{ + template<typename TyIt> + friend auto UnordMapDisjointSetFindRoot(TyIt it)-> decltype(&*it); + template<typename TyIt> + friend auto UnordMapDisjointSetUnion(TyIt it1, TyIt it2)-> decltype(&*it1); +private: + typename UnordMapDisjointSet<TyKey, TyValue, TyHash, TyEqual>::pointer pPr= nullptr;//´æ´¢Ö¸Õë + size_t rank = 0;//ÖÈ£¬Ëã·¨Óà + bool bRoot = true;//¼Ç¼ÊÇ·ñΪ¸ù£¬Îª¸ùʱ²»Ðè±£Ö¤Ö¸ÕëÓÐЧ +public: + //¹¹Ô캯Êý + template<typename ...Ty_S> + UnordMapDisjointSetNode(Ty_S &&...arg_s): + ValueHolder<TyValue>(std::forward<Ty_S>(arg_s)...) + { + } + //ÒýÓÃÔʼÊý¾Ý + typename ValueHolder<TyValue>::RefType Get() + { + return this->hold; + } + typename ValueHolder<TyValue>::ConstRefType Get() const + { + return this->hold; + } +}; +//¹þÏ£²¢²é¼¯¾²Ì¬Ëã·¨£¬ÕÒ¸ù½Úµã£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷ +template<typename TyIt> +inline auto UnordMapDisjointSetFindRoot(TyIt it)-> decltype(&*it) +{ + if(it->second.bRoot) + return &*it; + else { + auto itRes = UnordMapDisjointSetFindRoot(it->second.pPr); + it->second.pPr = &*itRes; + return it->second.pPr; + } +} +//¹þÏ£²¢²é¼¯¾²Ì¬Ëã·¨£¬ºÏ²¢¼¯ºÏ£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷£¬·µ»Ø¸ù +template<typename TyIt> +inline auto UnordMapDisjointSetUnion(TyIt it1, TyIt it2)-> decltype(&*it1) +{ + auto root1= UnordMapDisjointSetFindRoot(it1), + root2= UnordMapDisjointSetFindRoot(it2); + if(root1==root2) + return root1; + if(root1->second.rank<=root2->second.rank) { + //1Á¬µ½2ÉÏ + root1->second.pPr = root2; + root1->second.bRoot = false; + if(root1->second.rank==root2->second.rank) + ++ root2->second.rank; + return root2; + } + else { + //2Á¬µ½1ÉÏ + root2->second.pPr = root1; + root2->second.bRoot = false; + return root1; + } +} + + + +//Æ¥ÅäÊ÷ÄÚ²¿½ÚµãÀàÐÍ£¬Æ½ºâÊ÷ʵÏÖ +template<typename TyMatch, typename TyData> +struct _TrieTreeNode +{ + using RetDataType = TyData *; + using ConstRetDataType = const TyData *; + constexpr static bool bIsVoid = false; +public: + TyData *pData = nullptr; + std::map<TyMatch, _TrieTreeNode<TyMatch, TyData>> mapCh;//×ÓÊ÷ +public: + _TrieTreeNode() + = default; + ~_TrieTreeNode() + { + delete pData; + } + //¿½±´º¯Êý + _TrieTreeNode(const _TrieTreeNode &other) + { + operator =(other); + } + _TrieTreeNode &operator =(const _TrieTreeNode &other) + { + if(this!=&other) { + //Èô¶Ô·½ÓÐÊý¾Ý + if(other.pData) { + if(pData) + *pData = *other.pData; + else + Construct(other.data); + } + //Èô¶Ô·½Ã»Êý¾Ý + else { + if(pData) { + delete pData; + pData = nullptr; + } + } + //¿½±´ÆäËûÊý¾Ý + mapCh = other.mapCh; + } + return *this; + } + //¹¹ÔìÊý¾Ý + template<typename ...Ty_S> + void Construct(Ty_S &&...arg_s) + { + assert(pData==nullptr); + pData = new TyData(std::forward<Ty_S>(arg_s)...); + } + //Çå³ýÊý¾Ý + void Clear() + { + delete pData; + pData = nullptr; + mapCh.clear(); + } + //»ñÈ¡Êý¾ÝÖ¸Õë + static RetDataType GetData(_TrieTreeNode *pt) + { + if(pt==nullptr) + return nullptr; + else + return pt->pData; + } + static ConstRetDataType GetData(const _TrieTreeNode *pt) + { + return GetData((_TrieTreeNode *)pt); + } +}; +template<typename TyMatch> +struct _TrieTreeNode<TyMatch, void> +{ + using RetDataType = bool; + using ConstRetDataType = bool; + constexpr static bool bIsVoid = true; +public: + bool bData = false;//ÊÇ·ñÓÐÊý¾Ý + std::map<TyMatch, _TrieTreeNode<TyMatch, void>> mapCh;//×ÓÊ÷ +public: + //¹¹ÔìÊý¾Ý + void Construct() + { + bData = true; + } + //Çå³ýÊý¾Ý + void Clear() + { + bData = false; + mapCh.clear(); + } + //»ñÈ¡Êý¾Ý±êÇ© + static ConstRetDataType GetData(const _TrieTreeNode *pt) + { + if(pt==nullptr) + return false; + else + return pt->bData; + } +}; + +//Æ¥ÅäÊ÷ÄÚ²¿½ÚµãÀàÐÍ£¬¹þÏ£±íʵÏÖ +template<typename TyMatch, typename TyData> +struct _UnordTrieTreeNode +{ + using RetDataType = TyData *; + using ConstRetDataType = const TyData *; + constexpr static bool bIsVoid = false; +public: + TyData *pData = nullptr; + std::unordered_map<TyMatch, _UnordTrieTreeNode<TyMatch, TyData>> mapCh;//×ÓÊ÷ +public: + _UnordTrieTreeNode() + = default; + ~_UnordTrieTreeNode() + { + delete pData; + } + //¿½±´º¯Êý + _UnordTrieTreeNode(const _UnordTrieTreeNode &other) + { + operator =(other); + } + _UnordTrieTreeNode &operator =(const _UnordTrieTreeNode &other) + { + if(this!=&other) { + //Èô¶Ô·½ÓÐÊý¾Ý + if(other.pData) { + if(pData) + *pData = *other.pData; + else + Construct(other.data); + } + //Èô¶Ô·½Ã»Êý¾Ý + else { + if(pData) { + delete pData; + pData = nullptr; + } + } + //¿½±´ÆäËûÊý¾Ý + mapCh = other.mapCh; + } + return *this; + } + //¹¹ÔìÊý¾Ý + template<typename ...Ty_S> + void Construct(Ty_S &&...arg_s) + { + assert(pData==nullptr); + pData = new TyData(std::forward<Ty_S>(arg_s)...); + } + //Çå³ýÊý¾Ý + void Clear() + { + delete pData; + pData = nullptr; + mapCh.clear(); + } + //»ñÈ¡Êý¾ÝÖ¸Õë + static RetDataType GetData(_UnordTrieTreeNode *pt) + { + if(pt==nullptr) + return nullptr; + else + return pt->pData; + } + static ConstRetDataType GetData(const _UnordTrieTreeNode *pt) + { + return GetData((_UnordTrieTreeNode *)pt); + } +}; +template<typename TyMatch> +struct _UnordTrieTreeNode<TyMatch, void> +{ + using RetDataType = bool; + using ConstRetDataType = bool; + constexpr static bool bIsVoid = true; +public: + bool bData = false;//ÊÇ·ñÓÐÊý¾Ý + std::unordered_map<TyMatch, _UnordTrieTreeNode<TyMatch, void>> mapCh;//×ÓÊ÷ +public: + //¹¹ÔìÊý¾Ý + void Construct() + { + bData = true; + } + //Çå³ýÊý¾Ý + void Clear() + { + bData = false; + mapCh.clear(); + } + //»ñÈ¡Êý¾Ý±êÇ© + static ConstRetDataType GetData(const _UnordTrieTreeNode *pt) + { + if(pt==nullptr) + return false; + else + return pt->bData; + } +}; + +//binfile½Ó¿Ú¸¨Öú£¬¿ÉÒÔ¼æÈݺóÃæµÄAcMachineNode +template<typename TyNode> +inline typename std::enable_if<!TyNode::bIsVoid, void +>::type _BinWriteTrieOrAcNodeAssist(BinWriteFile &bwf, TyNode &node) +{ + uint8_t bData = node.pData!=nullptr; + bwf <<bData; + if(bData) + bwf <<*node.pData; + bwf <<node.mapCh; +} +template<typename TyNode> +inline typename std::enable_if<TyNode::bIsVoid, void +>::type _BinWriteTrieOrAcNodeAssist(BinWriteFile &bwf, TyNode &node) +{ + bwf <<(uint8_t)node.bData; + bwf <<node.mapCh; +} +template<typename TyNode> +inline typename std::enable_if<!TyNode::bIsVoid, void +>::type _BinReadTrieOrAcNodeAssist(BinReadFile &brf, TyNode &node) +{ + uint8_t bData; + brf >>bData; + //Èô¶Ô·½ÓÐÊý¾Ý + if(bData) { + if(node.pData==nullptr) + node.Construct(); + brf >>*node.pData; + } + //Èô¶Ô·½Ã»Êý¾Ý + else { + if(node.pData) { + delete node.pData; + node.pData = nullptr; + } + } + brf >>node.mapCh; +} +template<typename TyNode> +inline typename std::enable_if<TyNode::bIsVoid, void +>::type _BinReadTrieOrAcNodeAssist(BinReadFile &brf, TyNode &node) +{ + uint8_t bData; + brf >>bData; + node.bData = bData; + brf >>node.mapCh; +} + +//binfile½Ó¿Ú +template<typename TyMatch, typename TyData> +inline BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeNode<TyMatch, TyData> &node) +{ + _BinWriteTrieOrAcNodeAssist(bwf, node); + return bwf; +} +template<typename TyMatch, typename TyData> +inline BinReadFile &operator >>(BinReadFile &brf, _TrieTreeNode<TyMatch, TyData> &node) +{ + _BinReadTrieOrAcNodeAssist(brf, node); + return brf; +} +template<typename TyMatch, typename TyData> +inline BinWriteFile &operator <<(BinWriteFile &bwf, const _UnordTrieTreeNode<TyMatch, TyData> &node) +{ + _BinWriteTrieOrAcNodeAssist(bwf, node); + return bwf; +} +template<typename TyMatch, typename TyData> +inline BinReadFile &operator >>(BinReadFile &brf, _UnordTrieTreeNode<TyMatch, TyData> &node) +{ + _BinReadTrieOrAcNodeAssist(brf, node); + return brf; +} + +template<typename TyNode> +class _TrieTreeTemplate; +//Ê÷ÐÎÆ¥Åä½á¹¹ÉÏÏÂÎÄ +template<typename TyNode, typename TyIt> +struct _TrieContextTemplate +{ + bool bFirst = true;//¼Ç¼Ê×´ÎÆ¥Åä + TyNode *pt;//Ê÷½ÚµãÖ¸Õë + TyIt it;//Æ¥Åä´®Ö¸Õë +}; +template<typename TyNode, typename TyIt> +inline _TrieContextTemplate<TyNode, TyIt> MakeTrieContext(const _TrieTreeTemplate<TyNode> &, TyIt) +{ + return _TrieContextTemplate<TyNode, TyIt>(); +} + +//Ê÷×´´®Æ¥Åä½á¹¹£¬Ö§³ÖvoidÊý¾Ý +template<typename TyNode> +class _TrieTreeTemplate +{ + template<typename TyNode2> + friend BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeTemplate<TyNode2> &trie); + template<typename TyNode2> + friend BinReadFile &operator >>(BinReadFile &brf, _TrieTreeTemplate<TyNode2> &trie); + +public: + //¸¨ÖúÀàÐÍ + using NodeType = TyNode; + using RetDataType = typename NodeType::RetDataType; + using ConstRetDataType = typename NodeType::ConstRetDataType; + +private: + NodeType *pRoot;//Ê÷¸ù½Úµã + +public: + //Î忽±´ + _TrieTreeTemplate(): + pRoot(new NodeType) + { + } + ~_TrieTreeTemplate() + { + delete pRoot; + } + _TrieTreeTemplate(const _TrieTreeTemplate &other): + _TrieTreeTemplate() + { + operator =(other); + } + _TrieTreeTemplate(_TrieTreeTemplate &&other): + _TrieTreeTemplate() + { + operator =(std::move(other)); + } + _TrieTreeTemplate &operator =(const _TrieTreeTemplate &other) + { + if(this!=&other) { + *pRoot = *other.pRoot; + } + return *this; + } + _TrieTreeTemplate &operator =(_TrieTreeTemplate &&other) + { + if(this!=&other) { + std::swap(pRoot, other.pRoot); + } + return *this; + } +private: + //Õҽڵ㸨Öúº¯Êý£¬¿Õ´®¿ÉÒÔÆ¥Åä¿ÕÆ¥Å䣬pNode·µ»ØÆ¥ÅäµÄ½Úµã»ò¿Õ + //itSt·µ»ØÆ¥ÅäµÄβºó£¬bShortÕÒµ½¼´½áÊø£¬bBlankÔÊÐí¿ÕÆ¥Å䣬bAdd²éÕÒʱÏòºóÌí¼Ó + template<typename TyIt> + static void FindAssist(NodeType *&pNode, TyIt &itSt, TyIt itEd, + bool bShort, bool bBlank, bool bAdd) + { + //ÅжϿÕÖ¸Õë + if(pNode==nullptr) + return; + //ÔÊÐíΪ¿ÕʱµÄ´¦Àí + if(bBlank) { + //Ìáǰ½áÊøÇÒÆ¥Å䣬»òÒѾûÓÐÆ¥ÅäºóÐø£¬Ôò·µ»Ø³õʼ½Úµã + if((bShort && NodeType::GetData(pNode)) || itSt==itEd) + return; + } + //ÈôÌáǰ½áÊøÊ§°ÜÇÒûÓкóÐøÆ¥Å䣬ÔòÈÏΪÕÒ²»µ½ + if(itSt==itEd) { + pNode = nullptr; + } + //Ö÷Ñ»· + while(itSt!=itEd) {//µü´úÆ÷½áÊøÔòÌø³ö£¬´Ëʱ·µ»ØÖµÎªÕÒµ½µÄ½Úµã + //¸ù¾ÝÌí¼ÓÇé¿öÏòºóµü´ú + if(bAdd) + pNode = &pNode->mapCh[*itSt]; + else { + auto itPr = pNode->mapCh.find(*itSt); + //²»Ìí¼ÓÇÒÕÒ²»µ½¾Í·µ»Ø¿Õ + if(itPr==pNode->mapCh.end()) { + pNode = nullptr; + break; + } + pNode = &itPr->second; + } + ++ itSt; + //ÅÐÌáǰ½áÊø£¬´Ëʱµü´úÆ÷ÒѳÉΪβºó + if(bShort && NodeType::GetData(pNode)) + break; + } + } +public: + //Ìí¼ÓÆ¥Å乿Ôò + template<typename TyIt, typename ...Ty_S> + bool EmplaceRule(TyIt itSt, TyIt itEd, Ty_S &&...arg_s) + { + NodeType *pNode = pRoot; + FindAssist(pNode, itSt, itEd, false, true, true); + if(NodeType::GetData(pNode)) + return false; + pNode->Construct(std::forward<Ty_S>(arg_s)...); + return true; + } + //Çå³ý½Úµã + void Clear() + { + pRoot->Clear(); + } + //Æ¥ÅäÍêÕû´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û + //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õë»ò·ñ£¬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖà + template<typename TyIt> + std::pair<TyIt, RetDataType> Match(TyIt itSt, TyIt itEd) + { + NodeType *pNode = pRoot; + FindAssist(pNode, itSt, itEd, false, true, false); + return std::make_pair(itSt, NodeType::GetData(pNode)); + } + template<typename TyIt> + std::pair<TyIt, ConstRetDataType> Match(TyIt itSt, TyIt itEd) const + { + return ((_TrieTreeTemplate *)this)->Match(itSt, itEd); + } + //µü´úËÑË÷´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û + //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖà + //ctx³õʼ¸³Ä¬ÈϹ¹Ô죬֮ºóÁ¬ÐøÊ¹ÓôË×÷ΪÖмä¼þ + template<typename TyIt, typename TyCtx= _TrieContextTemplate<TyNode, TyIt>> + typename std::enable_if<IsRemoveCVRefSame<_TrieContextTemplate<TyNode, TyIt>, + TyCtx>::value, std::pair<TyIt, RetDataType> + >::type Search(TyIt itSt, TyIt itEd, TyCtx &&ctx= TyCtx()) + { + bool bBlank = false; + if(ctx.bFirst) { + ctx.bFirst = false; + ctx.pt = pRoot; + ctx.it = itSt; + bBlank = true;//µÚÒ»´Î¿ÉÒÔÆ¥Åä¿Õ£¬Îª±£Ö¤ÍƽøºóÐø²»ÐÐ + } + FindAssist(ctx.pt, ctx.it, itEd, true, bBlank, false); + return std::make_pair(ctx.it, NodeType::GetData(ctx.pt)); + } + template<typename TyIt, typename TyCtx= _TrieContextTemplate<TyNode, TyIt>> + typename std::enable_if<IsRemoveCVRefSame<_TrieContextTemplate<TyNode, TyIt>, + TyCtx>::value, std::pair<TyIt, ConstRetDataType> + >::type Search(TyIt itSt, TyIt itEd, TyCtx &&ctx= TyCtx()) const + { + return ((_TrieTreeTemplate *)this)->Search(itSt, itEd, ctx); + } + //Æ¥Åä×´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û + //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖà + template<typename TyIt> + std::pair<TyIt, RetDataType> SearchLong(TyIt itSt, TyIt itEd) + { + _TrieContextTemplate<TyNode, TyIt> ctx; + //Ê×ÏȲéÕÒÒ»´Î + auto ret = Search(itSt, itEd, ctx); + //ÈôÕҵõ½Ôò¼ÌÐøÕÒ + if(ret.second) { + while(true) { + auto tmp = Search(itSt, itEd, ctx); + if(!tmp.second) + break; + ret = tmp; + } + } + return ret; + } + template<typename TyIt> + std::pair<TyIt, ConstRetDataType> SearchLong(TyIt itSt, TyIt itEd) const + { + return ((_TrieTreeTemplate *)this)->SearchLong(itSt, itEd); + } + //ÕÒµ½µÚÒ»¸ö + template<typename TyIt> + RetDataType Judge(TyIt itSt, TyIt itEd) + { + return Search(itSt, itEd).second; + } + template<typename TyIt> + ConstRetDataType Judge(TyIt itSt, TyIt itEd) const + { + return ((_TrieTreeTemplate *)this)->Judge(itSt, itEd); + } + //¼ÆÊýÕÒµ½´ÎÊý + template<typename TyIt> + size_t Count(TyIt itSt, TyIt itEd) const + { + _TrieContextTemplate<TyNode, TyIt> ctx; + size_t cnt = 0; + for(; ; ++cnt) { + if(!Search(itSt, itEd, ctx).second) + break; + } + return cnt; + } +}; + +//binfile½Ó¿Ú +template<typename TyNode> +inline BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeTemplate<TyNode> &trie) +{ + return bwf <<*trie.pRoot; +} +template<typename TyNode> +inline BinReadFile &operator >>(BinReadFile &brf, _TrieTreeTemplate<TyNode> &trie) +{ + return brf >>*trie.pRoot; +} + +//¶¨ÒåËÑË÷Ê÷µÄƽºâÊ÷ʵÏÖ +template<typename TyMatch, typename TyData= void> +using TrieTree = _TrieTreeTemplate<_TrieTreeNode<TyMatch, TyData>>; +template<typename TyMatch, typename TyData, typename TyIt> +using TrieContext = _TrieContextTemplate<_TrieTreeNode<TyMatch, TyData>, TyIt>; +//¶¨ÒåËÑË÷Ê÷µÄ¹þÏ£±íʵÏÖ +template<typename TyMatch, typename TyData= void> +using UnordTrieTree = _TrieTreeTemplate<_UnordTrieTreeNode<TyMatch, TyData>>; +template<typename TyMatch, typename TyData, typename TyIt> +using UnordTrieContext = _TrieContextTemplate<_UnordTrieTreeNode<TyMatch, TyData>, TyIt>; + + + +//KMPËÑË÷ÀàÉÏÏÂÎÄ +template<typename TyItT, typename TyItP> +struct KmpContext +{ + ptrdiff_t cnt = -1;//ÒÑÆ¥ÅäµÄ¸öÊý£¬¸ºÊý±íʾδ³õʼ»¯ + TyItP itSub;//Æ¥Åäģʽ´®µÄµü´úλÖà + TyItT it;//Îı¾´®Î»Öà + TyItT itTFlag;//Îı¾´®¶ÔÆë¿ªÊ¼Î»Öà +}; +template<typename TyItT, typename TyItP> +inline KmpContext<TyItT, TyItP> MakeKmpContext(TyItT, TyItP) +{ + return KmpContext<TyItT, TyItP>(); +} + +//KMPËÑË÷Àà +class KmpSearcher +{ + std::vector<ptrdiff_t> vecSub;//¼Ç¼ÓÒÒÆµÄ³¤¶È£¬µÚiÏî¼Ç¼µÄÊÇÒÑÆ¥Åäi+1¸öºóµÄÒÆ¶¯³¤¶È£¬¼´Ï±êiλÖà +public: + KmpSearcher() + = default; + template<typename TyIt> + KmpSearcher(TyIt itSt, TyIt itEd) + { + Assign(itSt, itEd); + } +public: + //¸³Öµº¯Êý + template<typename TyIt> + KmpSearcher &Assign(TyIt itSt, TyIt itEd) + { + vecSub.resize(std::distance(itSt, itEd)); + if(vecSub.empty()) + return *this; + vecSub[1-1] = 1;//ÈôÒÑÆ¥Åä1¸ö£¬ÔòÓ¦¸ÃÓÒÒÆ1 + ptrdiff_t cnt = 0;//ÒÑÆ¥ÅäµÄ¸öÊý + auto itSub = itSt;//Æ¥Åäģʽ´®µÄµü´úλÖà + ptrdiff_t locate = 1;//µ±Ç°¶ÁÈ¡´®µÄϱê + //Ö÷ÌåÑ»· + for(++itSt; itSt!=itEd; ++itSt, ++locate) { + while(cnt!=0 && *itSt!=*itSub) { + //¸Ä±ä¶ÔÆëλÖúͳ¤¶È + std::advance(itSub, -vecSub[cnt-1]); + cnt -= vecSub[cnt-1]; + } + if(*itSt==*itSub) + ++ cnt, ++itSub; + vecSub[locate] = (locate+1-cnt); + } + return *this; + } + //ËÑË÷º¯Êý£¬Ö§³ÖΪ¿ÕÆ¥Å䣬ÈôÕÒµ½µü´úÆ÷Ϊָ¶¨´®£¬Î´ÕÒµ½µü´úÆ÷¾ùΪ´®Î²ºó + template<typename TyItT, typename TyItP, typename TyCtx= KmpContext<TyItT, TyItP>> + typename std::enable_if<IsRemoveCVRefSame<KmpContext<TyItT, TyItP>, TyCtx>::value, + std::pair<TyItT, TyItT> + >::type Search(TyItT itTSt, TyItT itTEd, TyItP itPSt, TyItP itPEd, + TyCtx &&ctx= TyCtx()) const + { + assert(std::distance(itPSt, itPEd)==vecSub.size()); + //³õʼ»¯ + if(ctx.cnt<0) { + ctx.cnt = 0; + ctx.it = itTSt; + ctx.itSub = itPSt; + ctx.itTFlag = itTSt; + } + //ÅжϿմ®Æ¥Åä + if(itPSt==itPEd) { + auto ret = std::make_pair(ctx.itTFlag, ctx.it); + ++ ctx.it, ctx.itTFlag; + return ret; + } + //Ö÷ÌåÑ»· + for(; ctx.it!=itTEd; ++ctx.it) { + while(ctx.cnt!=0 && *ctx.it!=*ctx.itSub) { + //¸Ä±ä¶ÔÆëλÖúͳ¤¶È + std::advance(ctx.itSub, -vecSub[ctx.cnt-1]); + std::advance(ctx.itTFlag, vecSub[ctx.cnt-1]); + ctx.cnt -= vecSub[ctx.cnt-1]; + } + if(*ctx.it==*ctx.itSub) { + ++ ctx.cnt, ++ctx.itSub; + if(ctx.cnt==vecSub.size()) { + //ÏÂÒ»¸öÑ»·Á¿ + ++ ctx.it; + auto ret = std::make_pair(ctx.itTFlag, ctx.it); + //¸Ä±ä¶ÔÆëλÖúͳ¤¶È + std::advance(ctx.itSub, -vecSub[ctx.cnt-1]); + std::advance(ctx.itTFlag, vecSub[ctx.cnt-1]); + ctx.cnt -= vecSub[ctx.cnt-1]; + return ret; + } + } + else + ++ ctx.itTFlag; + } + return std::make_pair(itTEd, itTEd); + } + //ÅжÏÊÇ·ñÕÒµ½ + template<typename TyItT, typename TyItP> + bool Judge(TyItT itTSt, TyItT itTEd, TyItP itPSt, TyItP itPEd) const + { + return Search(itTSt, itTEd, itPSt, itPEd).first!=itTEd; + } + //¼ÆÊýÕÒµ½´ÎÊý + template<typename TyItT, typename TyItP> + size_t Conut(TyItT itTSt, TyItT itTEd, TyItP itPSt, TyItP itPEd) const + { + KmpContext<TyItT, TyItP> ctx; + size_t cnt = 0; + for(; ; ++cnt) { + if(Search(itTSt, itTEd, itPSt, itPEd, ctx).first==itTEd) + break; + } + return cnt; + } +}; + + + +//AC×Ô¶¯»úÄÚ²¿½ÚµãÀàÐÍ£¬Æ½ºâÊ÷ʵÏÖ +template<typename TyMatch, typename TyData> +struct _AcMachineNode +{ + using RetDataType = TyData *; + using ConstRetDataType = const TyData *; + constexpr static bool bIsVoid = false; +public: + TyData *pData = nullptr; + std::map<TyMatch, _AcMachineNode> mapCh;//×ÓÊ÷ + size_t layer = 0;//µ±Ç°²ã + _AcMachineNode *pBack = nullptr;//»ØËݽڵãÖ¸Õë + _AcMachineNode *pFind = nullptr;//²éÕÒÓÐЧ½ÚµãÖ¸Õë +public: + _AcMachineNode() + = default; + ~_AcMachineNode() + { + delete pData; + } + //¿½±´º¯Êý£¬¿½±´ºóÐèÒªÖØÐ¹¹ÔìÖ¸Õë + _AcMachineNode(const _AcMachineNode &other) + { + operator =(other); + } + _AcMachineNode &operator =(const _AcMachineNode &other) + { + if(this!=&other) { + mapCh = other.mapCh; + //Èô¶Ô·½ÓÐÊý¾Ý + if(other.pData) { + if(pData) + *pData = *other.pData; + else + Construct(other.data); + } + //Èô¶Ô·½Ã»Êý¾Ý + else { + if(pData) { + delete pData; + pData = nullptr; + } + } + //¿½±´ÆäËûÊý¾Ý + mapCh = other.mapCh; + layer = other.layer; + pBack = nullptr; + pFind = nullptr; + } + return *this; + } + //¹¹ÔìÊý¾Ý + template<typename ...Ty_S> + void Construct(Ty_S &&...arg_s) + { + assert(pData==nullptr); + pData = new TyData(std::forward<Ty_S>(arg_s)...); + } + //Çå³ýÊý¾Ý + void Clear() + { + delete pData; + pData = nullptr; + mapCh.clear(); + } + //»ñÈ¡Êý¾ÝÖ¸Õë + static RetDataType GetData(_AcMachineNode *pt) + { + if(pt==nullptr) + return nullptr; + else + return pt->pData; + } + static ConstRetDataType GetData(const _AcMachineNode *pt) + { + return GetData((_AcMachineNode *)pt); + } +}; +template<typename TyMatch> +struct _AcMachineNode<TyMatch, void> +{ + using RetDataType = bool; + using ConstRetDataType = bool; + constexpr static bool bIsVoid = true; +public: + bool bData = false;//ÊÇ·ñÓÐÊý¾Ý + std::map<TyMatch, _AcMachineNode> mapCh;//×ÓÊ÷ + size_t layer = 0;//µ±Ç°²ã + _AcMachineNode *pBack = nullptr;//»ØËݽڵãÖ¸Õë + _AcMachineNode *pFind = nullptr;//²éÕÒÓÐЧ½ÚµãÖ¸Õë +public: + _AcMachineNode() + = default; + _AcMachineNode(const _AcMachineNode &other) + { + operator =(other); + } + //¿½±´º¯Êý£¬¿½±´ºóÐèÒªÖØÐ¹¹ÔìÖ¸Õë + _AcMachineNode &operator =(const _AcMachineNode &other) + { + if(this!=&other) { + bData = other.bData; + mapCh = other.mapCh; + layer = other.layer; + pBack = nullptr; + pFind = nullptr; + } + } + //¹¹ÔìÊý¾Ý + void Construct() + { + bData = true; + } + //Çå³ýÊý¾Ý + void Clear() + { + bData = false; + mapCh.clear(); + } + //»ñÈ¡Êý¾Ý±êÇ© + static ConstRetDataType GetData(const _AcMachineNode *pt) + { + if(pt==nullptr) + return false; + else + return pt->bData; + } +}; + +//AC×Ô¶¯»úÄÚ²¿½ÚµãÀàÐÍ£¬¹þÏ£±íʵÏÖ +template<typename TyMatch, typename TyData> +struct _UnordAcMachineNode +{ + using RetDataType = TyData *; + using ConstRetDataType = const TyData *; + constexpr static bool bIsVoid = false; +public: + TyData *pData = nullptr; + std::unordered_map<TyMatch, _UnordAcMachineNode> mapCh;//×ÓÊ÷ + size_t layer = 0;//µ±Ç°²ã + _UnordAcMachineNode *pBack = nullptr;//»ØËݽڵãÖ¸Õë + _UnordAcMachineNode *pFind = nullptr;//²éÕÒÓÐЧ½ÚµãÖ¸Õë +public: + _UnordAcMachineNode() + = default; + ~_UnordAcMachineNode() + { + delete pData; + } + //¿½±´º¯Êý£¬¿½±´ºóÐèÒªÖØÐ¹¹ÔìÖ¸Õë + _UnordAcMachineNode(const _UnordAcMachineNode &other) + { + operator =(other); + } + _UnordAcMachineNode &operator =(const _UnordAcMachineNode &other) + { + if(this!=&other) { + mapCh = other.mapCh; + //Èô¶Ô·½ÓÐÊý¾Ý + if(other.pData) { + if(pData) + *pData = *other.pData; + else + Construct(other.data); + } + //Èô¶Ô·½Ã»Êý¾Ý + else { + if(pData) { + delete pData; + pData = nullptr; + } + } + //¿½±´ÆäËûÊý¾Ý + mapCh = other.mapCh; + layer = other.layer; + pBack = nullptr; + pFind = nullptr; + } + return *this; + } + //¹¹ÔìÊý¾Ý + template<typename ...Ty_S> + void Construct(Ty_S &&...arg_s) + { + assert(pData==nullptr); + pData = new TyData(std::forward<Ty_S>(arg_s)...); + } + //Çå³ýÊý¾Ý + void Clear() + { + delete pData; + pData = nullptr; + mapCh.clear(); + } + //»ñÈ¡Êý¾ÝÖ¸Õë + static RetDataType GetData(_UnordAcMachineNode *pt) + { + if(pt==nullptr) + return nullptr; + else + return pt->pData; + } + static ConstRetDataType GetData(const _UnordAcMachineNode *pt) + { + return GetData((_UnordAcMachineNode *)pt); + } +}; +template<typename TyMatch> +struct _UnordAcMachineNode<TyMatch, void> +{ + using RetDataType = bool; + using ConstRetDataType = bool; + constexpr static bool bIsVoid = true; +public: + bool bData = false;//ÊÇ·ñÓÐÊý¾Ý + std::unordered_map<TyMatch, _UnordAcMachineNode> mapCh;//×ÓÊ÷ + size_t layer = 0;//µ±Ç°²ã + _UnordAcMachineNode *pBack = nullptr;//»ØËݽڵãÖ¸Õë + _UnordAcMachineNode *pFind = nullptr;//²éÕÒÓÐЧ½ÚµãÖ¸Õë +public: + _UnordAcMachineNode() + = default; + _UnordAcMachineNode(const _UnordAcMachineNode &other) + { + operator =(other); + } + //¿½±´º¯Êý£¬¿½±´ºóÐèÒªÖØÐ¹¹ÔìÖ¸Õë + _UnordAcMachineNode &operator =(const _UnordAcMachineNode &other) + { + if(this!=&other) { + bData = other.bData; + mapCh = other.mapCh; + layer = other.layer; + pBack = nullptr; + pFind = nullptr; + } + } + //¹¹ÔìÊý¾Ý + void Construct() + { + bData = true; + } + //Çå³ýÊý¾Ý + void Clear() + { + bData = false; + mapCh.clear(); + } + //»ñÈ¡Êý¾Ý±êÇ© + static ConstRetDataType GetData(const _UnordAcMachineNode *pt) + { + if(pt==nullptr) + return false; + else + return pt->bData; + } +}; + +//binfile½Ó¿Ú +template<typename TyMatch, typename TyData> +inline BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineNode<TyMatch, TyData> &node) +{ + _BinWriteTrieOrAcNodeAssist(bwf, node); + return bwf; +} +template<typename TyMatch, typename TyData> +inline BinReadFile &operator >>(BinReadFile &brf, _AcMachineNode<TyMatch, TyData> &node) +{ + _BinReadTrieOrAcNodeAssist(brf, node); + return brf; +} +template<typename TyMatch, typename TyData> +inline BinWriteFile &operator <<(BinWriteFile &bwf, const _UnordAcMachineNode<TyMatch, TyData> &node) +{ + _BinWriteTrieOrAcNodeAssist(bwf, node); + return bwf; +} +template<typename TyMatch, typename TyData> +inline BinReadFile &operator >>(BinReadFile &brf, _UnordAcMachineNode<TyMatch, TyData> &node) +{ + _BinReadTrieOrAcNodeAssist(brf, node); + return brf; +} + +template<typename TyNode> +class _AcMachineTemplate; +//AC×Ô¶¯»úËÑË÷ÀàÉÏÏÂÎÄ +template<typename TyNode, typename TyIt> +struct _AcContextTemplate +{ + bool bFirst = true;//¼Ç¼Ê×´ÎÆ¥Åä + TyNode *pt = nullptr;//Ê÷½ÚµãÖ¸Õë + TyNode *pFind = nullptr;//ÕýÔÚ²éÕÒÖ¸Õë + TyIt it;//Æ¥Åä´®Ö¸Õë +}; +template<typename TyNode, typename TyIt> +inline _AcContextTemplate<TyNode, TyIt> MakeAcContext(const _AcMachineTemplate<TyNode> &, TyIt) +{ + return _AcContextTemplate<TyNode, TyIt>(); +} + +//AC×Ô¶¯»úËÑË÷À֧࣬³ÖvoidÊý¾Ý +template<typename TyNode> +class _AcMachineTemplate +{ + template<typename TyNode2> + friend BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineTemplate<TyNode2> &acm); + template<typename TyNode2> + friend BinReadFile &operator >>(BinReadFile &brf, _AcMachineTemplate<TyNode2> &acm); + +public: + //¸¨ÖúÀàÐÍ + using NodeType = TyNode; + using RetDataType = typename NodeType::RetDataType; + using ConstRetDataType = typename NodeType::ConstRetDataType; + +private: + NodeType *pRoot;//¸ù½Úµã + bool bPrepare = true; + +public: + //Î忽±´ + _AcMachineTemplate(): + pRoot(new NodeType()) + { + } + ~_AcMachineTemplate() + { + delete pRoot; + } + _AcMachineTemplate(const _AcMachineTemplate &other): + _AcMachineTemplate() + { + operator =(other); + } + _AcMachineTemplate(_AcMachineTemplate &&other): + _AcMachineTemplate() + { + operator =(std::move(other)); + } + _AcMachineTemplate &operator =(const _AcMachineTemplate &other) + { + if(this!=&other) { + *pRoot = *other.pRoot; + bPrepare = false; + if(other.bPrepare) { + bPrepare = false; + Prepare(); + } + } + return *this; + } + _AcMachineTemplate &operator =(_AcMachineTemplate &&other) + { + if(this!=&other) { + std::swap(pRoot, other.pRoot); + std::swap(bPrepare, other.bPrepare); + } + return *this; + } +public: + //×ö×¼±¸£¬ÔÚ½øÐÐÆ¥Åä֮ǰµ÷Óã¬Ò²¿ÉÊÖ¶¯µ÷Óà + void Prepare() + { + if(bPrepare) + return; + std::deque<NodeType *> deqNode;//½ÚµãÕ¹¿ª¶ÓÁÐ + //¹¹ÔìµÚÒ»²ã»ØËÝ + deqNode.push_back(pRoot); + //Õ¹¿ª¶ÓÁÐ + while(!deqNode.empty()) { + //ÿһ¸ö×Ó½Úµã + for(auto &pr: deqNode.front()->mapCh) { + //Ìí¼Ó¶ÓÁÐ + deqNode.push_back(&pr.second); + //ѰÕÒ¸¸½Úµã + auto pFindBack = deqNode.front(); + while(pFindBack->pBack!=nullptr) { + pFindBack = pFindBack->pBack; + auto res = pFindBack->mapCh.find(pr.first); + if(res!=pFindBack->mapCh.end()) { + pFindBack = &res->second; + break; + } + } + //¹¹Ô츸ָÕë + pr.second.pBack = pFindBack; + if(NodeType::GetData(pFindBack)) + pr.second.pFind = pFindBack; + else + pr.second.pFind = pFindBack->pFind; + pr.second.layer = deqNode.front()->layer+1; + } + //µ¯³ö¶ÓÁÐ + deqNode.pop_front(); + } + bPrepare = true; + } + //Ìí¼ÓÆ¥Å乿Ôò + template<typename TyIt, typename ...Ty_S> + bool EmplaceRule(TyIt itSt, TyIt itEd, Ty_S &&...arg_s) + { + bPrepare = false; + NodeType *pNode = pRoot; + while(itSt!=itEd) { + auto res = pNode->mapCh.emplace(std::piecewise_construct, + std::tie(*itSt), std::make_tuple()); + pNode = &res.first->second; + bPrepare = bPrepare && !res.second; + ++ itSt; + } + if(NodeType::GetData(pNode)) + return false; + pNode->Construct(std::forward<Ty_S>(arg_s)...); + return true; + } + //Çå³ý½Úµã + void Clear() + { + pRoot->Clear(); + bPrepare = true; + } + //µü´úËÑË÷º¯Êý£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û + //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½·µ»ØÕÒµ½Î²ºóºÍ³¤¶È£¬Î´ÕÒµ½·µ»Ø´®Î²ºóºÍ0 + template<typename TyIt, typename TyCtx= _AcContextTemplate<TyNode, TyIt>> + typename std::enable_if<IsRemoveCVRefSame<_AcContextTemplate<TyNode, TyIt>, TyCtx>::value, + std::tuple<TyIt, size_t, RetDataType> + >::type Search(TyIt itSt, TyIt itEd, TyCtx &&ctx= TyCtx()) + { + //×¼±¸ + Prepare(); + //³õʼ»¯ + bool bFirst = false; + if(ctx.bFirst) { + ctx.bFirst = false; + ctx.pt = pRoot; + ctx.it = itSt; + bFirst = true; + } + auto ret = std::make_tuple(ctx.it, (size_t)0, NodeType::GetData((NodeType *)nullptr)); + //ÅжÏÊä³öͬһ½Úµã½á¹û + if(ctx.pFind!=nullptr) { + std::get<1>(ret) = ctx.pFind->layer; + std::get<2>(ret) = NodeType::GetData(ctx.pFind); + ctx.pFind = ctx.pFind->pFind; + } + //ÈôΪµÚÒ»´Î²éÕÒÇÒ´æÔÚ¿ÕÆ¥Åä + else if(bFirst && NodeType::GetData(ctx.pt)) { + std::get<1>(ret) = ctx.pt->layer; + std::get<2>(ret) = NodeType::GetData(ctx.pt); + ctx.pFind = ctx.pt->pFind; + } + //·ñÔò²éÕÒÏÂÒ»½Úµã + else { + //¶ÁÈë×Ö·ûÑ»· + while(ctx.it!=itEd) { + //²éÕÒ»ØËÝ + while(true) { + auto res = ctx.pt->mapCh.find(*ctx.it); + if(res!=ctx.pt->mapCh.end()) { + ctx.pt = &res->second; + break; + } + if(ctx.pt->pBack==nullptr) + break; + ctx.pt = ctx.pt->pBack; + } + ++ ctx.it; + //ÈôÕÒµ½´øÊý¾ÝµÄ½Úµã + if(NodeType::GetData(ctx.pt)) { + std::get<1>(ret) = ctx.pt->layer; + std::get<2>(ret) = NodeType::GetData(ctx.pt); + ctx.pFind = ctx.pt->pFind; + break; + } + //ÈôÕÒµ½´ø²éÕÒÊý¾ÝµÄ½Úµã + else if(ctx.pt->pFind!=nullptr) { + ctx.pFind = ctx.pt->pFind; + std::get<1>(ret) = ctx.pFind->layer; + std::get<2>(ret) = NodeType::GetData(ctx.pFind); + ctx.pFind = ctx.pFind->pFind; + break; + } + } + std::get<0>(ret) = ctx.it; + } + return ret; + } + //ÕÒµ½µÚÒ»¸ö£¬Æ¥Åäβºó¿¼Ç°ÓÅÏÈ£¬Æ¥ÅäÊײ¿¿¿Ç°ÓÅÏÈ + template<typename TyIt> + RetDataType Judge(TyIt itSt, TyIt itEd) + { + return std::get<2>(Search(itSt, itEd)); + } + //¼ÆÊýÕÒµ½´ÎÊý + template<typename TyIt> + RetDataType Count(TyIt itSt, TyIt itEd) + { + _AcContextTemplate<TyNode, TyIt> ctx; + size_t cnt = 0; + for(; ; ++cnt) { + if(std::get<2>(Search(itSt, itEd, ctx))) + break; + } + return cnt; + } +}; + +//binfile½Ó¿Ú +template<typename TyNode> +inline BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineTemplate<TyNode> &acm) +{ + return bwf <<(uint8_t)acm.bPrepare + <<*acm.pRoot; +} +template<typename TyNode> +inline BinReadFile &operator >>(BinReadFile &brf, _AcMachineTemplate<TyNode> &acm) +{ + uint8_t bPrepare; + brf >>bPrepare; + acm.bPrepare = false; + brf >>*acm.pRoot; + if(bPrepare) + acm.Prepare(); + return brf; +} + +//¶¨ÒåËÑË÷Ê÷µÄƽºâÊ÷ʵÏÖ +template<typename TyMatch, typename TyData= void> +using AcMachine = _AcMachineTemplate<_AcMachineNode<TyMatch, TyData>>; +template<typename TyMatch, typename TyData, typename TyIt> +using AcContext = _AcContextTemplate<_AcMachineNode<TyMatch, TyData>, TyIt>; +//¶¨ÒåËÑË÷Ê÷µÄ¹þÏ£±íʵÏÖ +template<typename TyMatch, typename TyData= void> +using UnordAcMachine = _AcMachineTemplate<_UnordAcMachineNode<TyMatch, TyData>>; +template<typename TyMatch, typename TyData, typename TyIt> +using UnordAcContext = _AcContextTemplate<_UnordAcMachineNode<TyMatch, TyData>, TyIt>; + + + + +//Ö»ÄÜÌí¼ÓÔªËØµÄͼ£¬Ö§³ÖvoidÊý¾ÝÀàÐÍ +//ÄÚ²¿Îª¶þάÊý×éʵÏÖ +//½Úµãµü´úÆ÷ÔÊÐíʹÓÃÕûÐÎË÷Òý¹¹Ôì +//ClearºÍAssign»áµ¼Öµü´úÆ÷ʧЧ +//ÈÝÆ÷¸´ÖÆ¡¢Òƶ¯¡¢½»»»ºóµü´úÆ÷¾ùÖ¸Ïò¾ÉÈÝÆ÷£¬ÔÊÐíµü´úÆ÷¸üÐÂÈÝÆ÷Ö¸Õë +//TODO: Ïë½á¹¹Éè¼Æ£¬³¢ÊÔ½«½ÚµãÓë±ß¶ÔÓ¦µ½ÕûÐÎË÷ÒýÉÏ +template<typename TyNodeData, typename TyEdgeData> +class AddonlyGraph +{ +private: + //±ß½á¹¹Ìå + struct EdgeStruct: + public ValueHolder<TyEdgeData> + { + size_t index;//±ß±àºÅ + //½ÓÊÕÊý¾ÝÀàÐÍÄ£°å²ÎÊýµÄ¹¹Ôì + template<typename ...Tys> + EdgeStruct(size_t o_index, Tys &&...args): + ValueHolder<TyEdgeData>(std::forward<Tys>(args)...), index(o_index) + { + } + }; + //½Úµã½á¹¹Ìå + struct NodeStruct: + public ValueHolder<TyNodeData> + { + std::vector<EdgeStruct> vecEdge;//³ö±ßÊý×é + //½ÓÊÕ×óÖµ»òÓÒÖµµÄÊý¾Ý¹¹Ôì + template<typename ...Tys> + NodeStruct(Tys &&...args): + ValueHolder<TyNodeData>(std::forward<Tys>(args)...) + { + } + }; + +private://¸¨ÖúÀàÐͶ¨Òå + using GraphType = AddonlyGraph<TyNodeData, TyEdgeData>;//ͼÀàÐÍ +public: + using NodeDataType = TyNodeData;//½ÚµãÊý¾ÝÀàÐÍ + using EdgeDataType = TyEdgeData;//±ßÊý¾ÝÀàÐÍ + +private://µü´úÆ÷Ä£°å¶¨Òå + //½Úµãµü´úÆ÷Ä£°å¸¨ÖúÀà + template<typename GraphTypeMy, typename TyNodeDataMy, typename TyNodeDataPure> + class TemplateNodeIterAssist; + //½Úµãµü´úÆ÷Ä£°å + template<typename GraphTypeMy, typename TyNodeDataMy, typename TyEdgeDataMy> + class TemplateNodeIter; + //±ßµü´úÆ÷Ä£°å¸¨ÖúÀà + template<typename GraphTypeMy, typename TyNodeDataMy, typename TyNodeDataPure> + class TemplateEdgeIterAssist; + //±ßµü´úÆ÷Ä£°å + template<typename GraphTypeMy, typename TyNodeDataMy, typename TyEdgeDataMy> + class TemplateEdgeIter; + +private://µü´úÆ÷Ä£°åÖ¸¶¨ÀàÐͶ¨Òå + //½Úµãµü´úÆ÷¸¨ÖúÀàÖ¸¶¨ + using NodeIterAssist = TemplateNodeIter<GraphType, TyNodeData, TyNodeData>; + //½Úµã³£µü´úÆ÷¸¨ÖúÀàÖ¸¶¨ + using NodeConstIterAssist = TemplateNodeIter< + const GraphType, const TyNodeData, TyNodeData>; + //±ßµü´úÆ÷¸¨ÖúÀàÖ¸¶¨ + using EdgeIterAssist = TemplateEdgeIter<GraphType, TyEdgeData, TyEdgeData>; + //±ß³£µü´úÆ÷¸¨ÖúÀàÖ¸¶¨ + using EdgeConstIterAssist = TemplateEdgeIter< + const GraphType, const TyEdgeData, TyEdgeData>; +public: + //½Úµãµü´úÆ÷ÀàÖ¸¶¨ + using NodeIter = TemplateNodeIter<GraphType, TyNodeData, TyEdgeData>; + //½Úµã³£µü´úÆ÷ÀàÖ¸¶¨ + using NodeConstIter = TemplateNodeIter< + const GraphType, const TyNodeData, const TyEdgeData>; + //±ßµü´úÆ÷ÀàÖ¸¶¨ + using EdgeIter = TemplateEdgeIter<GraphType, TyNodeData, TyEdgeData>; + //±ß³£µü´úÆ÷ÀàÖ¸¶¨ + using EdgeConstIter = TemplateEdgeIter< + const GraphType, const TyNodeData, const TyEdgeData>; + +public://ÓÑÔªÉùÃ÷ + friend NodeIter; + friend NodeIterAssist; + friend NodeConstIter; + friend NodeConstIterAssist; + friend EdgeIter; + friend EdgeIterAssist; + friend EdgeConstIter; + friend EdgeConstIterAssist; + +private://³ÉÔ±Êý¾Ý + std::vector<NodeStruct> vecNode;//½ÚµãÊý×é + +public://»ù±¾º¯Êý + //ĬÈϹ¹Ôì + AddonlyGraph() + = default; + //¶à¸öÊý¾Ý¹¹Ôì + template<typename ...Ty_S> + explicit AddonlyGraph(size_t size, const Ty_S &...arg_s) + { + Assign(size, arg_s...); + } +public://³ÉÔ±º¯Êý + //¸³Öµº¯Êý + template<typename ...Ty_S> + AddonlyGraph &Assign(size_t size, const Ty_S &...arg_s) + { + vecNode.assign(size, NodeStruct(arg_s...)); + return *this; + } + //Ìí¼Ó½Úµã + template<typename TyNodeDataMy> + typename std::enable_if<std::is_convertible<TyNodeDataMy &&, TyNodeData>::value, NodeIter + >::type AddNode(TyNodeDataMy &&data) + { + return EmplaceNode(std::forward<TyNodeDataMy>(data)); + } + template<typename ...Tys> + NodeIter EmplaceNode(Tys &&...args) + { + vecNode.emplace_back(std::forward<Tys>(args)...); + return NodeIter(this, vecNode.size()-1); + } + //Ìí¼Ó±ß + template<typename TyEdgeDataMy> + typename std::enable_if<std::is_convertible<TyEdgeDataMy &&, TyEdgeData>::value, EdgeIter + >::type AddEdge(NodeIter fromNode, NodeIter toNode, TyEdgeDataMy &&data) + { + return EmplaceEdge(fromNode, toNode, std::forward<TyEdgeDataMy>(data)); + } + //¹¹Ôì±ß + template<typename ...Tys> + EdgeIter EmplaceEdge(NodeIter fromNode, NodeIter toNode, Tys &&...args) + { + vecNode[fromNode.idxNode].vecEdge.emplace_back( + toNode.idxNode, std::forward<Tys>(args)...); + return EdgeIter(this, fromNode.idxNode, vecNode[fromNode.idxNode].vecEdge.size()-1); + } + //Ìí¼ÓË«Ïò±ß + template<typename TyEdgeDataMy> + typename std::enable_if<std::is_convertible<TyEdgeDataMy &&, TyEdgeData>::value, + std::pair<EdgeIter, EdgeIter> + >::type AddDoublyEdge(NodeIter fromNode, NodeIter toNode, + TyEdgeDataMy &&dataGo, TyEdgeDataMy &&dataRev) + { + auto it = AddAdge(fromNode, toNode, std::forward<TyEdgeDataMy>(dataGo)); + return std::make_pair(it, + AddAdge(toNode, fromNode, std::forward<TyEdgeDataMy>(dataRev))); + } +private: + //¹¹ÔìË«Ïò±ß¸¨Öúº¯Êý + template<typename TyTupGo, typename TyTupRev, size_t ...c_idxGo_s, size_t ...c_idxRev_s> + std::pair<EdgeIter, EdgeIter> EmplaceDoublyEdgeAssist(NodeIter fromNode, + NodeIter toNode, TyTupGo &&tupGo, TyTupRev &&tupRev, + IndexSequence<c_idxGo_s...>, IndexSequence<c_idxRev_s...>) + { + static auto funcGo = std::mem_fn(&AddonlyGraph::EmplaceEdge< + typename TypeAttachAttribute<TyTupGo &&, typename std::tuple_element< + c_idxGo_s, typename RemoveCVRef<TyTupGo>::type>::type>::type...>); + static auto funcRev = std::mem_fn(&AddonlyGraph::EmplaceEdge< + typename TypeAttachAttribute<TyTupRev &&, typename std::tuple_element< + c_idxRev_s, typename RemoveCVRef<TyTupRev>::type>::type>::type...>); + auto itGo = TupleInvoke(funcGo, + std::tuple_cat(std::forward_as_tuple(this, fromNode, toNode), std::forward<TyTupGo>(tupGo))); + auto itRev = TupleInvoke(funcRev, + std::tuple_cat(std::forward_as_tuple(this, toNode, fromNode), std::forward<TyTupRev>(tupRev))); + return std::make_pair(itGo, itRev); + } +public: + //¹¹ÔìË«Ïò±ß£¬ÔÚtupleÀïÃæ·Å¹¹Ôì²ÎÊý + template<typename TyTupGo, typename TyTupRev> + std::pair<EdgeIter, EdgeIter> EmplaceDoublyEdge(NodeIter fromNode, + NodeIter toNode, TyTupGo &&tupGo, TyTupRev &&tupRev) + { + return EmplaceDoublyEdgeAssist(fromNode, toNode, + std::forward<TyTupGo>(tupGo), std::forward<TyTupRev>(tupRev), + MakeIndexSequence<std::tuple_size< + typename std::remove_reference<TyTupGo>::type>::value>(), + MakeIndexSequence<std::tuple_size< + typename std::remove_reference<TyTupRev>::type>::value>()); + } + //Çå³ýͼ + void Clear() + { + vecNode.clear(); + } + //µü´ú½Úµã + NodeIter NodeBegin() + { + return NodeIter(this, 0); + } + NodeConstIter NodeBegin() const + { + return NodeConstIter(this, 0); + } + NodeIter begin() + { + return NodeBegin(); + } + NodeConstIter begin() const + { + return NodeBegin(); + } + NodeConstIter NodeConstBegin() + { + return NodeBegin(); + } + NodeIter NodeEnd() + { + return NodeIter(this, vecNode.size()); + } + NodeConstIter NodeEnd() const + { + return NodeConstIter(this, vecNode.size()); + } + NodeIter end() + { + return NodeEnd(); + } + NodeConstIter end() const + { + return NodeEnd(); + } + NodeConstIter NodeConstEnd() + { + return NodeEnd(); + } + //½ÚµãÊý + size_t NodeSize() const + { + return vecNode.size(); + } +}; + +//µãµü´úÆ÷Ä£°å¸¨ÖúÀà +template<typename TyNodeData, typename TyEdgeData> +template<typename GraphTypeMy, typename TyNodeDataMy, typename TyNodeDataPure> +class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateNodeIterAssist: + public std::iterator<std::bidirectional_iterator_tag, TyNodeDataMy, + ptrdiff_t, TyNodeDataMy *, TyNodeDataMy &> +{ +protected://³ÉÔ±Êý¾Ý + GraphTypeMy *pGraph;//ͼָÕë + size_t idxNode;//½Úµã + +public://»ù±¾º¯Êý + //ĬÈϹ¹Ôì + TemplateNodeIterAssist(): + pGraph(nullptr), idxNode(0) + { + } + //¹¹Ô캯Êý£¬ÔÊÐíÍⲿ½øÐй¹Ôì + explicit TemplateNodeIterAssist(GraphTypeMy *o_graph, size_t o_idxNode): + pGraph(o_graph), idxNode(o_idxNode) + { + } +public://ÔËËã·ûÖØÔØ + //½âÒýÓòÙ×÷ + TyNodeDataMy &operator *() const + { + return pGraph->vecNode[idxNode].hold; + } + TyNodeDataMy *operator ->() const + { + return &operator *(); + } +}; +//µãµü´úÆ÷Ä£°å¸¨ÖúÀàÌØ»¯ +template<typename TyNodeData, typename TyEdgeData> +template<typename GraphTypeMy, typename TyNodeDataMy> +class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateNodeIterAssist< + GraphTypeMy, TyNodeDataMy, void +>: public std::iterator<std::bidirectional_iterator_tag, TyNodeDataMy, + ptrdiff_t, void, void> +{ +protected://³ÉÔ±Êý¾Ý + GraphTypeMy *pGraph;//ͼָÕë + size_t idxNode;//½Úµã + +public://»ù±¾º¯Êý + //ĬÈϹ¹Ôì + TemplateNodeIterAssist(): + pGraph(nullptr), idxNode(0) + { + } + //¹¹Ô캯Êý£¬ÔÊÐíÍⲿ½øÐй¹Ôì + explicit TemplateNodeIterAssist(GraphTypeMy *o_graph, size_t o_idxNode): + pGraph(o_graph), idxNode(o_idxNode) + { + } +}; + +//½Úµãµü´úÆ÷Ä£°åÀà +template<typename TyNodeData, typename TyEdgeData> +template<typename GraphTypeMy, typename TyNodeDataMy, typename TyEdgeDataMy> +class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateNodeIter: + public TemplateNodeIterAssist<GraphTypeMy, TyNodeDataMy, TyNodeData> +{ +public://ÓÑÔª + friend AddonlyGraph<TyNodeData, TyEdgeData>; + friend NodeIter; + friend NodeConstIter; + friend EdgeIter; + friend EdgeConstIter; +private://¸¨ÖúÀàÐÍ + //¶ÔÓ¦µÄ±ßµü´úÆ÷ + using EdgeIterMy = TemplateEdgeIter<GraphTypeMy, TyNodeDataMy, TyEdgeDataMy>; + +public://»ù±¾º¯Êý + //ĬÈϹ¹Ôì + TemplateNodeIter() + = default; + //¼Ì³Ð¸¨ÖúÀàµÄ¹¹Ô캯Êý + using TemplateNodeIterAssist<GraphTypeMy, TyNodeDataMy, TyNodeData>::TemplateNodeIterAssist; + //Óɷdz£À๹Ôì³£Àà + TemplateNodeIter(const NodeIter &other) + { + operator =(other); + } + TemplateNodeIter &operator =(const NodeIter &other) + { + if((void *)this!=(void *)&other) { + this->pGraph = other.pGraph; + this->idxNode = other.idxNode; + } + return *this; + } +public://ÔËËã·ûÖØÔØ + //µÝÔöµÝ¼õ²Ù×÷ + TemplateNodeIter &operator ++() + { + ++ this->idxNode; + return *this; + } + TemplateNodeIter operator ++(int) + { + TemplateNodeIter ret(*this); + operator ++(); + return ret; + } + TemplateNodeIter &operator --() + { + -- this->idxNode; + return *this; + } + TemplateNodeIter operator --(int) + { + TemplateNodeIter ret(*this); + operator --(); + return ret; + } + //±È½Ï²Ù×÷ + template<typename GraphTypeOther, typename TyNodeDataOther, typename TyEdgeDataOther> + bool operator ==(const TemplateNodeIter< + GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const + { + return this->idxNode==other.idxNode; + } + template<typename GraphTypeOther, typename TyNodeDataOther, typename TyEdgeDataOther> + bool operator !=(const TemplateNodeIter< + GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const + { + return !operator ==(other); + } +public://³ÉÔ±º¯Êý + //³ö±ßµü´ú²Ù×÷ + EdgeIterMy EdgeBegin() const + { + return EdgeIterMy(this->pGraph, this->idxNode, 0); + } + EdgeIterMy begin() const + { + return EdgeBegin(); + } + EdgeConstIter EdgeConstBegin() const + { + return EdgeBegin(); + } + EdgeIterMy EdgeEnd() const + { + return EdgeIterMy(this->pGraph, this->idxNode, this->pGraph->vecNode[this->idxNode].vecEdge.size()); + } + EdgeIterMy end() const + { + return EdgeEnd(); + } + EdgeConstIter EdgeConstEnd() const + { + return EdgeEnd(); + } + //´¦±ßÊý + size_t EdgeSize() const + { + return this->pGraph->vecNode[this->idxNode].size(); + } + //¸Ä±äÖ¸Ïò²Ù×÷ + void ChangePointer(GraphTypeMy *o_graph) + { + this->pGraph = o_graph; + } +}; + +//±ß´úÆ÷Ä£°å¸¨ÖúÀà +template<typename TyNodeData, typename TyEdgeData> +template<typename GraphTypeMy, typename TyEdgeDataMy, typename TyEdgeDataPure> +class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateEdgeIterAssist: + public std::iterator<std::bidirectional_iterator_tag, TyEdgeDataMy, + ptrdiff_t, TyEdgeDataMy *, TyEdgeDataMy &> +{ +protected://³ÉÔ±Êý¾Ý + GraphTypeMy *pGraph;//ͼָÕë + size_t idxNode;//½ÚµãÐòºÅ + size_t idxEdge;//±ßÐòºÅ + +public://»ù±¾º¯Êý + //ĬÈϹ¹Ôì + TemplateEdgeIterAssist(): + pGraph(nullptr), idxNode(0), idxEdge(0) + { + } +protected: + //¹¹Ô캯Êý£¬²»ÔÊÐíÍⲿ½øÐй¹Ôì + explicit TemplateEdgeIterAssist(GraphTypeMy *o_graph, size_t o_idxNode, size_t o_idxEdge): + pGraph(o_graph), idxNode(o_idxNode), idxEdge(o_idxEdge) + { + } +public://ÔËËã·ûÖØÔØ + //½âÒýÓòÙ×÷ + TyEdgeDataMy &operator *() const + { + return pGraph->vecNode[idxNode].vecEdge[idxEdge].hold; + } + TyEdgeDataMy *operator ->() const + { + return &operator *(); + } +}; +//±ßµü´úÆ÷Ä£°å¸¨ÖúÀàÌØ»¯ +template<typename TyNodeData, typename TyEdgeData> +template<typename GraphTypeMy, typename TyEdgeDataMy> +class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateEdgeIterAssist< + GraphTypeMy, TyEdgeDataMy, void +>: public std::iterator<std::bidirectional_iterator_tag, TyEdgeDataMy, + ptrdiff_t, void, void> +{ +protected://³ÉÔ±Êý¾Ý + GraphTypeMy *pGraph;//ͼָÕë + size_t idxNode;//½ÚµãÐòºÅ + size_t idxEdge;//±ßÐòºÅ + +public://»ù±¾º¯Êý + //ĬÈϹ¹Ôì + TemplateEdgeIterAssist(): + pGraph(nullptr), idxNode(0), idxEdge(0) + { + } +protected: + //¹¹Ô캯Êý£¬²»ÔÊÐíÍⲿ½øÐй¹Ôì + explicit TemplateEdgeIterAssist(GraphTypeMy *o_graph, size_t o_idxNode, size_t o_idxEdge): + pGraph(o_graph), idxNode(o_idxNode), idxEdge(o_idxEdge) + { + } +}; + +//±ßµü´úÆ÷Ä£°åÀà +template<typename TyNodeData, typename TyEdgeData> +template<typename GraphTypeMy, typename TyNodeDataMy, typename TyEdgeDataMy> +class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateEdgeIter: + public TemplateEdgeIterAssist<GraphTypeMy, TyEdgeDataMy, TyEdgeData> +{ +public://ÓÑÔª + friend AddonlyGraph<TyNodeData, TyEdgeData>; + friend NodeIter; + friend NodeConstIter; + friend EdgeIter; + friend EdgeConstIter; +private://¸¨ÖúÀàÐÍ + //¶ÔÓ¦µÄ½Úµãµü´úÆ÷ + using NodeIterMy = TemplateNodeIter<GraphTypeMy, TyNodeDataMy, TyEdgeDataMy>; + +public://»ù±¾º¯Êý + //¼Ì³Ð¸¨ÖúÀàµÄ¹¹Ô캯Êý + using TemplateEdgeIterAssist<GraphTypeMy, TyEdgeDataMy, TyEdgeData>::TemplateEdgeIterAssist; + //Óɷdz£À๹Ôì³£Àà + TemplateEdgeIter(const EdgeIter &other) + { + operator =(other); + } + TemplateEdgeIter &operator =(const EdgeIter &other) + { + if((void *)this!=(void *)&other) { + this->pGraph = other.pGraph; + this->idxNode = other.idxNode; + this->idxEdge = other.idxEdge; + } + return *this; + } +public://ÔËËã·ûÖØÔØ + //µÝÔöµÝ¼õÔì×÷ + TemplateEdgeIter &operator ++() + { + ++ this->idxEdge; + return *this; + } + TemplateEdgeIter operator ++(int) + { + TemplateEdgeIter ret(*this); + operator ++(); + return ret; + } + TemplateEdgeIter &operator --() + { + -- this->idxEdge; + return *this; + } + TemplateEdgeIter operator --(int) + { + TemplateEdgeIter ret(*this); + operator --(); + return ret; + } + //±È½Ï²Ù×÷ + template<typename GraphTypeOther, typename TyNodeDataOther, typename TyEdgeDataOther> + bool operator ==(const TemplateEdgeIter< + GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const + { + return this->idxNode==other.idxNode && this->idxEdge==other.idxEdge; + } + template<typename GraphTypeOther, typename TyNodeDataOther, typename TyEdgeDataOther> + bool operator !=(const TemplateEdgeIter< + GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const + { + return !operator ==(other); + } +public://³ÉÔ±º¯Êý + //»ñÈ¡Á¬½Ó½Úµã + NodeIterMy NodeFrom() const + { + return NodeIterMy(this->pGraph, this->idxNode); + } + NodeConstIter NodeConstFrom() const + { + return NodeFrom(); + } + NodeIterMy NodeTo() const + { + return NodeIterMy(this->pGraph, this->pGraph->vecNode[this->idxNode].vecEdge[this->idxEdge].index); + } + NodeIterMy NodeConstTo() const + { + return NodeTo(); + } +}; + + +/*ͼ·ÖÀàÉèÏë + +1£¬Ö»ÄÜÌí¼ÓµÄͼ£º +AddNode +AddEdge +Clear +NodeBegin +NodeEnd +NodeIter::EdgeBegin +NodeIter::EdgeEnd +NodeIter::operator ++ +NodeIter::operator -- +NodeIter::operator * +EdgeIter::NodeFrom +EdgeIter::NodeTo +EdgeIter::operator ++ +NodeIter::operator -- +EdgeIter::operator * + +2£¬Ö»ÄÜÌí¼ÓµÄͼ£¬¿ÉÒԲ鿴À´Ô´±ß£º +È«²¿1º¯Êý +NodeIter::EdgeFromBegin +NodeIter::EdgeFromEnd + +3£¬Ö»ÄÜÌí¼ÓµÄͼ£¬¿ÉÒÔ¸ù¾ÝÁ½¸ö¶¥µãÕÒÀ´Ô´ +È«²¿1º¯Êý +GetEdge + +4£¬Ö»ÄÜÌí¼ÓµÄͼ£¬´øÓÐÁ½ÕßÊôÐÔ +È«²¿2£¬3º¯Êý + +5£¬¿ÉÒÔÐ޸ĵÄͼ +È«²¿1º¯Êý +È«²¿2º¯Êý +DelNode +DelEdge + +6£¬ÔÚ5»ù´¡ÉÏÔö¼Ó +3¹¦ÄÜ£¬»¹Ã»ÏëºÃ + +*/ + + + + +//µ¥´¿Ðνá¹û״̬ +enum class SimplexStatus +{ + result, infeasible, unbounded,//Óнá¹û£¬Î޽⣬ÎÞ½ç +}; + +//µ¥´¿Ðθ¨ÖúÐýת +template<typename Ty> +inline void _SimplexAssistPivot(std::vector<std::vector<Ty>> &aMatrix, std::vector<Ty> &bVector, + std::vector<Ty> &cVector, Ty &vValue, std::vector<int> &bSet, std::vector<int> &nSet, + int lIndex, int eIndex) +{ + int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý + //ת»»»»³ö±äÁ¿ËùÔÚÐÐÒ»ÐÐ + aMatrix[lIndex][eIndex] = 1/aMatrix[lIndex][eIndex]; + bVector[lIndex] *= aMatrix[lIndex][eIndex]; + for(int j=0; j<nNum; ++j) { + if(j==eIndex) + continue; + aMatrix[lIndex][j] *= aMatrix[lIndex][eIndex]; + } + //ת»»¾ØÕóÆäËûÐÐ + for(int i=0; i<mNum; ++i) { + if(i==lIndex) + continue; + bVector[i] -= aMatrix[i][eIndex]*bVector[lIndex]; + for(int j=0; j<nNum; ++j) { + if(j==eIndex) + continue; + aMatrix[i][j] -= aMatrix[i][eIndex]*aMatrix[lIndex][j]; + } + aMatrix[i][eIndex] *= -aMatrix[lIndex][eIndex]; + } + //ת»»Ä¿±êº¯Êý + vValue += cVector[eIndex]*bVector[lIndex]; + for(int j=0; j<nNum; ++j) { + if(j==eIndex) + continue; + cVector[j] -= cVector[eIndex]*aMatrix[lIndex][j]; + } + cVector[eIndex] *= -aMatrix[lIndex][eIndex]; + //ת»»Ë÷Òý + std::swap(bSet[lIndex], nSet[eIndex]); +} + +//µ¥´¿Ðθ¨ÖúË㷨ѻ·Ö÷Ìå +template<typename Ty> +inline SimplexStatus _SimplexAssistLoop(std::vector<std::vector<Ty>> &aMatrix, std::vector<Ty> &bVector, + std::vector<Ty> &cVector, Ty &vValue, std::vector<int> &bSet, std::vector<int> &nSet, int ulp) +{ + int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý + //µ¥´¿ÐÎÑ»· + while(true) { + //ÕÒ»»Èë»»³ö±äÁ¿Ñ»· + bool bFirst = true; + int lIndex, eIndex; + while(true) { + //ÕÒ»»Èë±äÁ¿ + eIndex = -1; + Ty maxC = -std::numeric_limits<Ty>::infinity(); + for(int j=0; j<nNum; ++j) { + if(bFirst) { + if(cVector[j]>maxC) { + eIndex = j; + maxC = cVector[j]; + } + } + else { + //ÍË»¯Ê±Ñ¡±êºÅ×îС + if(FloatGT(cVector[j], 0.0, true, ulp) && (eIndex==-1 || nSet[j]<nSet[eIndex])) { + eIndex = j; + maxC = cVector[j]; + } + } + } + if(FloatLTE(maxC, 0.0, true, ulp)) + return SimplexStatus::result; + //ÕÒ»»³ö±äÁ¿ + lIndex = -1; + Ty minB = std::numeric_limits<Ty>::infinity(); + for(int i=0; i<mNum; ++i) { + if(FloatGT(aMatrix[i][eIndex], 0.0, true, ulp)) { + Ty tmp = bVector[i]/aMatrix[i][eIndex]; + if(tmp<minB) { + minB = tmp; + lIndex = i; + } + } + } + //ÅжÏÎÞ½ç + if(lIndex==-1) { + vValue = std::numeric_limits<Ty>::infinity(); + return SimplexStatus::unbounded; + } + //ÍË»¯Ôò¼ÌÐøÑ»· + if(bFirst && FloatEQ(minB, 0.0, true, ulp)) + bFirst = false; + else + break; + } + //Ðýת + _SimplexAssistPivot(aMatrix, bVector, cVector, vValue, bSet, nSet, lIndex, eIndex); + } +} + +//µ¥´¿Ðθ¨Öú³õʼ»¯ +template<typename Ty> +inline SimplexStatus _SimplexAssistInit(std::vector<std::vector<Ty>> &aMatrix, std::vector<Ty> &bVector, + std::vector<Ty> &cVector, Ty &vValue, std::vector<int> &bSet, std::vector<int> &nSet, int ulp) +{ + int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý + //Åжϻù±¾½â¿ÉÐÐÐÔ + bool bPoss = true; + bSet.reserve(mNum); + nSet.reserve(nNum+1); + for(int j=0; j<nNum; ++j) + nSet.push_back(j); + Ty minB = std::numeric_limits<Ty>::infinity(); + int lIndex = -1; + for(int i=0; i<mNum; ++i) { + bSet.push_back(nNum+i); + if(bVector[i]<minB) { + minB = bVector[i]; + lIndex = i; + } + } + if(FloatGTE(minB, 0.0, true, ulp)) + return SimplexStatus::result; + //¹¹Ô츨Öú¹æ»® + Ty vValue2 = 0; + std::vector<Ty> cVector2(nNum+1, 0); + cVector2[nNum] = -1; + for(int i=0; i<mNum; ++i) + aMatrix[i].push_back(-1); + nSet.push_back(-1); + //³õʼÐýת²¢Çó½â + _SimplexAssistPivot(aMatrix, bVector, cVector2, vValue2, bSet, nSet, lIndex, nNum); + SimplexStatus status = _SimplexAssistLoop(aMatrix, bVector, cVector2, vValue2, bSet, nSet, ulp); + assert(status==SimplexStatus::result); + //ÅжϿÉÐÐÐÔ + status = FloatEQ(vValue2, 0.0, true, ulp) ? + SimplexStatus::result : SimplexStatus::infeasible; + //·´Ðýת¸¨Öú±äÁ¿ + lIndex = (int)(std::find(bSet.begin(), bSet.end(), -1)-bSet.begin()); + int eIndex; + if(lIndex!=mNum) { + eIndex = -1; + for(int j=0; j<nNum+1; ++j) { + if(FloatNEQ(aMatrix[lIndex][j], 0.0, true, ulp)) { + eIndex = j; + break; + } + } + assert(eIndex!=-1); + _SimplexAssistPivot(aMatrix, bVector, cVector2, vValue2, bSet, nSet, lIndex, eIndex); + } + else { + eIndex = (int)(std::find(nSet.begin(), nSet.end(), -1)-nSet.begin()); + assert(eIndex!=nNum+1); + } + //½»»»¸¨Öú±äÁ¿ + if(eIndex!=nNum) { + for(int i=0; i<mNum; ++i) + std::swap(aMatrix[i][eIndex], aMatrix[i][nNum]); + std::swap(nSet[eIndex], nSet[nNum]); + } + //È¥³ý¸¨Öú±äÁ¿ + for(int i=0; i<mNum; ++i) + aMatrix[i].pop_back(); + nSet.pop_back(); + cVector2.assign(nNum, 0); + for(int j=0; j<nNum; ++j) { + if(nSet[j]<nNum) + cVector2[j] = cVector[nSet[j]]; + } + for(int i=0; i<mNum; ++i) { + if(bSet[i]<nNum) { + vValue += cVector[bSet[i]]*bVector[i]; + for(int j=0; j<nNum; ++j) { + cVector2[j] -= cVector[bSet[i]]*aMatrix[i][j]; + } + } + } + std::swap(cVector, cVector2); + return status; +} + +//µ¥´¿Ð稣¬Ä£°åΪ¸¡µãÊý +//²ÎÊýΪ±ê×¼Ðͼ´£ºÏµÊý¾ØÕó¡¢³£ÊýÏòÁ¿¡¢Ä¿±êϵÊýÏòÁ¿¡¢Ä¿±ê³£ÊýÖµ£¬¸¡µã¾ø¶ÔÎó²î½ç±¶ÂÊ +//·µ»ØÖµÎª×´Ì¬¡¢½âÏòÁ¿¡¢»ù±¾±äÁ¿ÐòºÅ¡¢·Ç»ù±¾±äÁ¿ÐòºÅ +//aMatrix¡¢bVector¡¢cVectorÖоùΪΪ×îÖÕËɳÚÐ͵Ľṹ£¬vValueÊÇÄ¿±êÖµ +//±ê×¼Ð͵ÄÑùÀý£º +//MAX: cVector^T * x + vValue +//s.t.£ºaMatrix * x <= bVector +template<typename Ty> +inline typename std::enable_if<std::is_floating_point<Ty>::value, + std::tuple<SimplexStatus, std::vector<Ty>, std::vector<int>, std::vector<int>> +>::type SimplexAlgo(std::vector<std::vector<Ty>> &aMatrix, std::vector<Ty> &bVector, + std::vector<Ty> &cVector, Ty &vValue, int ulp= 2000) +{ + int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý + std::vector<int> bSet, nSet;//»ù±¾¡¢·Ç»ù±¾±äÁ¿Ë÷Òýϱê + std::vector<Ty> resVector;//½âϵÊýÏòÁ¿ + //ÕÒ³õʼ½â + SimplexStatus status = _SimplexAssistInit(aMatrix, bVector, cVector, vValue, bSet, nSet, ulp); + if(status==SimplexStatus::infeasible) + return make_tuple(status, resVector, bSet, nSet); + //µ¥´¿ÐÎÑ»· + status = _SimplexAssistLoop(aMatrix, bVector, cVector, vValue, bSet, nSet, ulp); + if(status==SimplexStatus::unbounded) + return make_tuple(status, resVector, bSet, nSet); + //Éú³É½âÏòÁ¿ + resVector.resize(nNum, 0); + for(int i=0; i<mNum; ++i) { + if(bSet[i]<nNum) + resVector[bSet[i]] = bVector[i]; + } + return make_tuple(status, std::move(resVector), std::move(bSet), std::move(nSet)); +} + 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); +} + diff --git a/UsedMacro.h b/UsedMacro.h new file mode 100644 index 0000000..44fc75a --- /dev/null +++ b/UsedMacro.h @@ -0,0 +1,166 @@ +#pragma once + +//³£Óú궨Òå¿â +//20191111-1705 + +#include <cstdio> +#include <cassert> + +#include <iostream> + +#include <type_traits> +#include <utility> + +#include <string> + +#include <exception> +#include <stdexcept> + + +//********** +//±êʶ·û²Ù×÷ +//********** + +#define SYMBOL_STR(id) #id//ת±ä×Ö·û´® + + + +#define CONNECT_SYMBOL_2(str1, str2) str1##str2 +#define CONNECT_SYMBOL_3(str1, str2, str3) str1##str2##str3 +#define CONNECT_SYMBOL_4(str1, str2, str3, str4) str1##str2##str3##str4 + + + +//************ +//ÊýÖµÔËËã²Ù×÷ +//************ + +#define NEG_TO(x) ((x) = -(x))//¸³Ïà·´Êý +#define NOT_TO(x) ((x) = !(x))//¸³²¼¶û·Ç +#define INV_TO(x) ((x) = ~(x))//¸³°´Î»È¡·´ + + +#define ABS_OF(x) ((x)>0? (x):-(x))//È¡¾ø¶ÔÖµ +#define ABS_TO(x) ((x) = ABS_OF(x))//¸³¾ø¶ÔÖµ + + +#define DIS_OF(x, y) (ABS_OF((x)-(y)))//È¡²îÖµ + + + +#define MAX_OF(x, y) ((x)>(y)? (x):(y))//È¡×î´óÖµ +#define MIN_OF(x, y) ((x)<(y)? (x):(y))//È¡×îСֵ + + +#define MAX_TO(x, lim) ((x) = MAX_OF(x, lim))//¸³×î´óÖµ +#define MIN_TO(x, lim) ((x) = MIN_OF(x, lim))//¸³×îСֵ + +#define HIGH_LIMIT(x, lim) MIN_TO(x, lim)//ÉèÖÃÉÏÏÞ +#define LOW_LIMIT(x, lim) MAX_TO(x, lim)//ÉèÖÃÏÂÏÞ + + +#define RANGE_OF(x, llim, hlim) ((x)<(llim)? (llim): (x)>(hlim)? (hlim):(x))//È¡·¶Î§ +#define RANGE_LIMIT(x, llim, hlim) ((x) = RANGE_OF(x, llim, hlim))//ÉèÖ÷¶Î§ + + +#define IS_IN_RANGE(x, llim, hlim) ((x)>=(llim) && (x)<=(hlim))//ÅжÏÊÇ·ñÔÚ·¶Î§ÄÚ +#define IS_IN_ITER_RANGE(x, st, ed) ((x)>=(st) && (x)<(ed))//ÅжÏÊÇ·ñÔÚ·¶Î§ÄÚ£¬ÒÔµü´úÆ÷±ê×¼ + + + +#define SQUARE_OF(x) ((x)*(x))//Ç󯽷½ +#define SQUARE_TO(x) ((x) = SQUARE_OF(x))//¸³ÖµÆ½·½ + + + +//************ +//ÔËËãÊ¡ÂÔ²Ù×÷ +//************ + + + +#define LIST_GO(p, m_p) ((p) = (p)->m_p)//Á´±íÖ¸ÕëÒÆ¶¯ + +#define LIST_CNNT(p1, m_p1, p2, m_p2) \ + (((p1)->m_p1=p2), ((p2)->m_p2=p1))//Ë«ÏòÁ´±íÁ¬½Ó + +#define LIST_ADD(p1, m_p1, p2, m_p2, pNew) \ + (LIST_CNNT(p1, m_p1, pNew, m_p2), LIST_CNNT(pNew, m_p1, p2, m_p2))//Ë«ÏòÁ´±íÌí¼Ó + + + +#define ARR_SIZE(arr) (sizeof(decltype(arr))\ + /sizeof(typename std::remove_extent<decltype(arr)>::type))//ÇóÊý×é´óС + +#define ARR_SIZE_ALL(arr) (sizeof(decltype(arr))\ + /sizeof(typename std::remove_all_extents<decltype(arr)>::type))//Çó¸ùÊý×é´óС + + + +#define SHOW_BEGIN_END(container) std::begin(container), std::end(container)//ÁгöÈÝÆ÷µÄbeginºÍendº¯Êý + + + +#define O_(id) CONNECT_SYMBOL_2(o_, id)//Ìí¼ÓÔʼǰ׺ + +#define O_INIT(id) id(O_(id))//ʹÓÃǰ׺°æ±¾³õʼ»¯ +#define O_INIT_MOVE(id) id(std::move(O_(id)))//ʹÓÃǰ׺°æ±¾Òƶ¯³õʼ»¯ +#define O_INIT_FORWARD(id, Ty) id(std::forward<Ty>(O_(id)))//ʹÓÃǰ׺°æ±¾×ª·¢³õʼ»¯ + +#define O_ASSIGN(id) (id = O_(id))//ʹÓÃǰ׺°æ±¾¸³Öµ +#define O_ASSING_MOVE(id) (id = std::move(O_(id)))//ʹÓÃǰ׺°æ±¾Òƶ¯¸³Öµ +#define O_ASSIGN_FORWARD(id, Ty) (id = std::forward<Ty>(O_(id)))//ʹÓÃǰ׺°æ±¾×ª·¢³õʼ»¯ + + +#define OTHER_INIT(other, mem) mem((other).mem)//ʹÓÃÀà³ÉÔ±³õʼ»¯ +#define OTHER_INIT_MOVE(other, mem) mem(std::move(other).mem)//ʹÓÃÀà³ÉÔ±ÒÆ¶¯³õʼ»¯ +#define OTHER_INIT_FORWARD(other, mem, Ty) mem(std::forward<Ty>(other).mem)//ʹÓÃÀà³ÉԱת·¢³õʼ»¯ + +#define OTHER_ASSIGN(other, mem) (mem = (other).mem)//ʹÓÃÀà³ÉÔ±¸³Öµ +#define OTHER_ASSIGN_MOVE(other, mem) (mem = std::move(other).mem)//ʹÓÃÀà³ÉÔ±ÒÆ¶¯¸³Öµ +#define OTHER_ASSIGN_FORWARD(other, mem) (mem = std::forward<Ty>(other).mem)//ʹÓÃÀà³ÉԱת·¢¸³Öµ + + + +//****** +//¶àÓï¾ä²Ù×÷ +//****** + +#define CLASS_ASSIGN(Type, other) {\ + if(this!=&(other)) {\ + this->~Type();\ + new(this) Type(other);\ + }}//¿½±´¸³Öµ£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓà + +#define CLASS_ASSIGN_MOVE(Type, other) {\ + if(this!=&(other)) {\ + this->~Type();\ + new(this) Type(std::move(other));\ + }}//ÒÆ¶¯¸³Öµ£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓà + + +#define TEMPLATE_ASSIGN(Type, Typename, arg) {\ + this->~Type();\ + new(this) Type(std::forward<Typename>(arg));\ + }//Ä£°å¸³Öµ£¬×Ô¸³Öµ²»°²È«£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓà + +#define TEMPLATE_PACKET_ASSIGN(Type, Typenames, args) {\ + this->~Type();\ + new(this) Type(std::forward<Typenames>(args)...);\ + }//Ä£°å°ü¸³Öµ£¬×Ô¸³Öµ²»°²È«£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓà + + + +//****** +//ÉùÃ÷²Ù×÷ +//****** + +#define DEFINE_INLINE_VERIABLE(Type, name) \ +inline Type &name() \ +{\ + static Type value;\ + return value;\ +}//¶¨ÒåÄÚÁª±äÁ¿ + +#define GET_INLINE_VARIABLE(name) name()//»ñÈ¡ÄÚÁª±äÁ¿ + diff --git a/makefile b/makefile new file mode 100644 index 0000000..31a5762 --- /dev/null +++ b/makefile @@ -0,0 +1,49 @@ +#编译器版本 +CC = gcc +CXX = g++ -std=c++11 +#附加头文件目录 +INCS_DIR = +#附加包含库目录 +LIBS_DIR = +#附加包含库文件 +DEF_LIBS = +STA_LIBS = +DYN_LIBS = +#预定义宏 +DEFINE = -D MAKEFILE_ENVIRONMENT +#编译选项 +CFLAGS = -g -Wall -O3 + +#目标生成文件名 +TARGETS = DomainDeal +#源文件 +C_SRCS = $(wildcard *.c */*.c) +CPP_SRCS = $(wildcard *.cpp */*.cpp) +#中间文件 +C_OBJS = $(patsubst %.c,%.o,$(C_SRCS)) +CPP_OBJS = $(patsubst %.cpp,%.o,$(CPP_SRCS)) +#依赖头文件 +HEADS = $(wildcard *.h */*.h *.hpp */*.hpp) + + +#生成目标 +$(TARGETS): $(C_OBJS) $(CPP_OBJS) + $(CXX) -o $@ $(CFLAGS) $(LIBS_DIR) $(C_OBJS) $(CPP_OBJS) \ + $(DEF_LIBS) -Wl,-Bstatic $(STA_LIBS) -Wl,-Bdynamic $(DYN_LIBS) + +#c生成.o +$(C_OBJS): %.o: %.c $(HEADS) + $(CC) -c $(CFLAGS) $(INCS_DIR) $(DEFINE) $(patsubst %.o,%.c,$@) +#cpp生成.o +$(CPP_OBJS): %.o: %.cpp $(HEADS) + $(CXX) -c $(CFLAGS) $(INCS_DIR) $(DEFINE) $(patsubst %.o,%.cpp,$@) + + +#清理文件命令 +.PHONY: clean +clean: + -rm $(TARGETS) $(C_OBJS) $(CPP_OBJS) + +#重构文件命令 +.PHONY: rebuild +rebuild: clean $(TARGETS)
\ No newline at end of file diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..34d3196 --- /dev/null +++ b/test.txt @@ -0,0 +1,5 @@ +this is head line +0 www.baidu.com 3 4 5 6 7 8 9 10 11 12 13 14 etc +0 1 www.google.com 3 4 5 6 7 8 9 10 11 12 13 14 +0 1 youku.com 3 4 5 6 7 8 9 10 11 12 13 14 etc + |
