Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // g++ 4.7.1, g++ 4.8 unstable, clang++ 3.1 ηΌθ―ιθΏ
- #if __cplusplus < 201103L
- # error C++11 support is needed
- #endif
- #include <cstdio>
- #include <type_traits>
- #include <array>
- constexpr int const_strcmp(const char *s1, const char *s2) {
- return *s1!=*s2 || *s1 == 0 || *s2 == 0 ? *s1 - *s2 : const_strcmp(s1+1, s2+1);
- }
- // unittest
- static_assert(const_strcmp("asdfzxcv", "asdfzxcv") == 0, "");
- static_assert(const_strcmp("asdfaxcv", "asdfzxcv") < 0, "");
- static_assert(const_strcmp("asdf", "asdfzxcv") < 0, "");
- template <typename Type, size_t Size>
- constexpr int const_arrcmp(const std::array<Type, Size>& arr1, const std::array<Type, Size>& arr2, const size_t idx = 0) {
- return idx == Size
- ? 0
- : (arr1[idx] == arr2[idx]
- ? const_arrcmp(arr1, arr2, idx + 1)
- : arr1[idx] - arr2[idx]
- );
- }
- // unittest
- static_assert(const_arrcmp(std::array<size_t, 4>{{1,2,3,4}}, std::array<size_t, 4>{{1,2,3,4}}) == 0, "");
- static_assert(const_arrcmp(std::array<size_t, 4>{{1,2,3,3}}, std::array<size_t, 4>{{1,2,3,4}}) < 0, "");
- static_assert(const_arrcmp(std::array<size_t, 4>{{1,2,3}}, std::array<size_t, 4>{{1,2,3,4}}) < 0, "");
- inline constexpr size_t percentCounter(const char *str) {
- return *str != '\0' ? percentCounter(str + 1) + (*str == '%') : 0;
- }
- // unittest
- static_assert(percentCounter("%%%%") == 4, "");
- static_assert(percentCounter("as%fd%ae%rew%") == 4, "");
- static_assert(percentCounter("") == 0, "");
- inline constexpr size_t percentSearch(const char *str, size_t idx, size_t pos = 0) {
- return *str == '\0'
- ? size_t(-1)
- : (*str == '%'
- ? (idx == 0
- ? pos
- : percentSearch(str + 1, idx - 1, pos + 1)
- )
- : percentSearch(str + 1, idx, pos + 1)
- );
- }
- // unittest
- static_assert(percentSearch("%%%%", 1) == 1, "");
- static_assert(percentSearch("111%%%%", 2) == 5, "");
- static_assert(percentSearch("1%11", 2) == size_t(-1), "");
- template <size_t argNum>
- class StrFormater {
- public:
- constexpr StrFormater(const char *fStr, std::array<size_t, argNum> args): formatStr(fStr), Args(args) {}
- constexpr bool operator ==(const StrFormater& rhs) {
- return const_strcmp(this->formatStr, rhs.formatStr) == 0
- && const_arrcmp(this->Args, rhs.Args) == 0;
- }
- constexpr bool operator !=(const StrFormater& rhs) {
- return !(*this == rhs);
- }
- const char *const formatStr;
- std::array<size_t, argNum> Args;
- };
- template <size_t N1, size_t N2>
- constexpr typename std::enable_if<N1 != N2, bool>::type operator ==(const StrFormater<N1>&, const StrFormater<N2>&) {
- return false;
- }
- template <size_t N1, size_t N2>
- constexpr typename std::enable_if<N1 != N2, bool>::type operator !=(const StrFormater<N1>&, const StrFormater<N2>&) {
- return true;
- }
- template<size_t... Seq>
- struct variadic_sequence
- {};
- template <size_t Max, size_t Now = 0>
- struct natural_sequence {
- template <size_t... Num>
- using type = typename natural_sequence<Max, Now + 1>::template type<Num..., Now>;
- };
- template <size_t Now>
- struct natural_sequence<Now, Now> {
- template <size_t... Num>
- using type = variadic_sequence<Num...>;
- };
- template <typename>
- struct make_formater_helper;
- template <size_t... Seq>
- struct make_formater_helper<variadic_sequence<Seq...>> {
- static constexpr StrFormater<sizeof...(Seq)> call(const char *str) {
- return StrFormater<sizeof...(Seq)>(str, std::array<size_t, sizeof...(Seq)>{ { percentSearch(str, Seq)... } });
- }
- };
- #define make_formater(FORMATSTR) (make_formater_helper<natural_sequence<percentCounter(FORMATSTR)>::type<>>::call(FORMATSTR))
- static_assert(make_formater("%d + %d = %d") == StrFormater<3>("%d + %d = %d", { {0, 5, 10} }), "");
- static_assert(make_formater("%d + %d = 1d") != StrFormater<3>("%d + %d = %d", { {0, 5, 10} }), "");
- static_assert(make_formater("%d + %d = %d") != StrFormater<3>("%d + %d = %d", { {0, 5, 11} }), "");
- static_assert(make_formater("%d + %d") != StrFormater<3>("%d + %d = %d", { {0, 5, 10} }), "");
- static_assert(make_formater("%d + %d") != StrFormater<2>("%d - %d", { {0, 5} }), "");
- int main() {
- using namespace std;
- auto f = make_formater("%d + %d = %d");
- for (auto i : f.Args)
- printf("%zd ", i);
- putchar('\n');
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement