[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:
parent
43b5d469b3
commit
41090efaf5
26
libvmake/examples/custom_sequence.cpp
Normal file
26
libvmake/examples/custom_sequence.cpp
Normal 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;
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user