diff --git a/sprout/stateful.hpp b/sprout/stateful.hpp index 6a9213cb..fa034f6b 100644 --- a/sprout/stateful.hpp +++ b/sprout/stateful.hpp @@ -14,5 +14,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_STATEFUL_HPP diff --git a/sprout/stateful/typed_counter.hpp b/sprout/stateful/typed_counter.hpp new file mode 100644 index 00000000..e1c8680f --- /dev/null +++ b/sprout/stateful/typed_counter.hpp @@ -0,0 +1,97 @@ +/*============================================================================= + Copyright (c) 2011-2015 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_STATEFUL_TYPED_COUNTER_HPP +#define SPROUT_STATEFUL_TYPED_COUNTER_HPP + +#include +#include + +namespace sprout { +#ifndef SPROUT_CONFIG_DISABLE_CONSTEXPR + + namespace typed_counter_detail { + template + struct typed { +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wnon-template-friend" +#endif +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wundefined-inline" +#endif + template + struct tag { + friend SPROUT_CONSTEXPR int adl_counter(tag); + }; +#if defined(__clang__) +# pragma clang diagnostic pop +#endif +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic pop +#endif + + template + struct state + : public sprout::integral_constant + { + friend SPROUT_CONSTEXPR int adl_counter(tag) { + return N; + } + }; + + template())> + static SPROUT_CONSTEXPR bool check(int, tag) { + return true; + } + template + static SPROUT_CONSTEXPR bool check(long, tag) { + return false; + } + template + static SPROUT_CONSTEXPR bool check(bool R = check(0, tag())) { + return R; + } + + template + static SPROUT_CONSTEXPR int counter(sprout::false_type, tag) { + return 0; + } + template + static SPROUT_CONSTEXPR int counter( + sprout::true_type, tag, + int R = !check() ? N + : counter(sprout::bool_constant()>(), tag()) + ) + { + return R; + } + template + static SPROUT_CONSTEXPR int counter(int R = counter(sprout::true_type(), tag())) { + return R; + } + }; + } // namespace typed_counter_detail + // + // counter + // + template< + typename T, + int N = 1, + int R = sprout::typed_counter_detail::typed::template state< + sprout::typed_counter_detail::typed::template counter(sprout::true_type(), typename sprout::typed_counter_detail::typed::template tag()) + N - 1 + >::value + > + SPROUT_CONSTEXPR int counter() { + return R; + } + +#endif +} // namespace sprout + +#endif // #ifndef SPROUT_STATEFUL_TYPED_COUNTER_HPP