#pragma once template class idSearch { public: virtual ~idSearch() = default; virtual int Search(const type* base, unsigned int num, const type& value) const = 0; virtual int Search_FirstGreater(const type* base, int num, const type& value) const = 0; virtual int Search_FirstGreaterEqual(const type* base, int num, const type& value) const = 0; virtual int Search_LastLess(const type* base, int num, const type& value) const = 0; virtual int Search_LastLessEqual(const type* base, int num, const type& value) const = 0; }; template class idSearch_Binary : public idSearch { public: int Search(const type* base, const unsigned int num, const type& value) const override { if (base == nullptr || num == 0) { return -1; } const int index = Search_LastLessEqual(base, static_cast(num), value); return Compare(base[index], value) == 0 ? index : -1; } int Search_FirstGreater(const type* base, const int num, const type& value) const override { int first = 0; int count = num < 0 ? 0 : num; while (count > 0) { const int step = count / 2; const int middle = first + step; if (Compare(base[middle], value) <= 0) { first = middle + 1; count -= step + 1; } else { count = step; } } return first; } int Search_FirstGreaterEqual(const type* base, const int num, const type& value) const override { int first = 0; int count = num < 0 ? 0 : num; while (count > 0) { const int step = count / 2; const int middle = first + step; if (Compare(base[middle], value) < 0) { first = middle + 1; count -= step + 1; } else { count = step; } } return first; } int Search_LastLess(const type* base, const int num, const type& value) const override { const int result = Search_FirstGreaterEqual(base, num, value) - 1; return result < 0 ? 0 : result; } int Search_LastLessEqual(const type* base, const int num, const type& value) const override { const int result = Search_FirstGreater(base, num, value) - 1; return result < 0 ? 0 : result; } private: int Compare(const type& left, const type& right) const { return static_cast(this)->Compare(left, right); } }; template class idSearch_BinaryDefault : public idSearch_Binary> { public: int Compare(const type& left, const type& right) const { if (left < right) { return -1; } if (right < left) { return 1; } return 0; } }; template using idSearch_DefaultCompare = idSearch_BinaryDefault;