[libvmake] add meta type vmake::is_sequence_t to check if a type is a valid sequence

fixed a bug with vmake::range(start, end, step)
added an example about how to define costum sequences
This commit is contained in:
方而静 2023-07-19 21:49:49 +08:00
parent 43b5d469b3
commit 41090efaf5
2 changed files with 66 additions and 6 deletions

View File

@ -0,0 +1,26 @@
#include "../vmake.hpp"
using namespace std;
// equivlant to vmake::range(2, 11, 2)
struct my_sequence {
using result = int;
int p;
my_sequence() : p(2) {}
bool is_terminated() const noexcept {
return p > 10;
}
int operator()() {
p += 2;
return p - 2;
}
};
int main() {
static_assert(vmake::is_sequence_t<my_sequence>::value, "my_sequence is not a valid sequence!");
vmake::outputln(cout, " ", my_sequence{});
vmake::outputln(cout, " ", vmake::range(2, 11, 2));
return 0;
}

View File

@ -19,8 +19,26 @@ struct sequence_terminated_error : std::exception {
}
};
namespace polyfill {
namespace details {
template<typename T>
auto is_sequence_helper(char)
-> decltype(
std::declval<T>()()
, std::declval<T>().is_terminated()
, typename std::enable_if<std::is_same<decltype(std::declval<T>()())
, typename T::result>::value, int>::type()
, std::true_type{});
template<typename T>
auto is_sequence_helper(int) -> std::false_type;
}
template<typename T>
using is_sequence_t = decltype(details::is_sequence_helper<T>(' '));
namespace polyfill {
#if __cplusplus >= 201703L
@ -46,7 +64,7 @@ struct iota_sequence {
using result = T;
T start;
iota_sequence(const T& start) : start(start) {}
iota_sequence(T&& start) : start(std::forward<T>(start)) {}
bool is_terminated() const noexcept {
return false;
@ -62,10 +80,11 @@ struct ranged_sequence {
using result = T;
T start, end;
ranged_sequence(const T& start, const T& end) : start(start), end(end) {}
ranged_sequence(T&& start, T&& end)
: start(std::forward<T>(start)), end(std::forward<T>(end)) {}
bool is_terminated() const noexcept {
return start == end;
return !(start < end);
}
auto operator()() {
@ -79,10 +98,12 @@ struct ranged_step_sequence {
using result = T;
T start, end, step;
ranged_step_sequence(const T& start, const T& end, const T& step) : start(start), end(end), step(step) {}
ranged_step_sequence(T&& start, T&& end, T&& step)
: start(std::forward<T>(start)), end(std::forward<T>(end))
, step(std::forward<T>(step)) {}
bool is_terminated() const noexcept {
return start == end;
return !(start < end);
}
auto operator()() {
@ -657,6 +678,19 @@ inline void outputln(std::basic_ostream<CharT, Traits>& out, const Endl &endl =
out << endl;
}
namespace tests {
using empty_sequence_int = decltype(nothing<int>());
static_assert(is_sequence_t<empty_sequence_int>::value, "");
static_assert(is_sequence_t<decltype(take(empty_sequence_int{}, 1))>::value, "");
static_assert(is_sequence_t<decltype(group<20>(empty_sequence_int{}))>::value, "");
static_assert(!is_sequence_t<int>::value, "");
static_assert(!is_sequence_t<std::less<int>>::value, "");
}
}
#endif