various warning fixes with -Weverything

master
Daniel Kolesa 2018-01-03 17:09:28 +01:00
parent 2cbcc85fa8
commit 723c06c612
19 changed files with 255 additions and 224 deletions

View File

@ -473,7 +473,7 @@ int main(int argc, char **argv) {
try_remove("test_runner.o");
};
ostd::thread_pool tp;
ostd::thread_pool tp{};
tp.start();
std::queue<std::future<fs::path>> future_obj, future_dynobj;

View File

@ -13,10 +13,10 @@ using namespace ostd;
* task, which may or may not run in parallel with the other one depending
* on the scheduler currently in use - several schedulers are shown
*/
auto input_array = { 150, 38, 76, 25, 67, 18, -15, 215, 25, -10 };
static auto input_array = { 150, 38, 76, 25, 67, 18, -15, 215, 25, -10 };
auto first_half = iter(input_array).slice(0, input_array.size() / 2);
auto second_half = iter(input_array).slice(input_array.size() / 2);
static auto first_half = iter(input_array).slice(0, input_array.size() / 2);
static auto second_half = iter(input_array).slice(input_array.size() / 2);
/* this version uses Go-style channels to exchange data; multiple
* tasks can put data into channels, the channel itself is a thread

View File

@ -9,7 +9,7 @@
using namespace ostd;
void list_dirs(filesystem::path const &path, int off = 0) {
inline void list_dirs(filesystem::path const &path, int off = 0) {
filesystem::directory_iterator ds{path};
for (auto &v: ds) {
auto p = filesystem::path{v};

View File

@ -33,7 +33,7 @@ int main() {
/* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */
writeln("string gen test");
auto mr = map(range(6), [](int v) -> char { return v + 65; });
auto mr = map(range(6), [](int v) { return char(v + 65); });
std::string s{mr.iter_begin(), mr.iter_end()};
writeln(s);

View File

@ -28,7 +28,7 @@ int main() {
/* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */
writeln("string gen test");
auto mr = range(6) | map([](int v) -> char { return v + 65; });
auto mr = range(6) | map([](int v) { return char(v + 65); });
std::string s{mr.iter_begin(), mr.iter_end()};
writeln(s);
@ -73,7 +73,7 @@ int main() {
/* more complex pipe */
writeln("several piped algorithms");
srand(time(0));
srand(static_cast<unsigned int>(time(0)));
std::array<int, 100> arr;
generate(iter(arr), []() { return rand() % 128; });

View File

@ -9,7 +9,7 @@
using namespace ostd;
void print_result(uint32_t x) {
inline void print_result(uint32_t x) {
writefln("got x: 0x%X", x);
}

View File

@ -135,7 +135,7 @@ struct parse_state {
((i + 1) < codes.size()) && (codes[i + 1] == (codes[i] + off))
);
};
auto match_range = [&codes, &cases, &match_pair](std::size_t i) {
auto match_range = [&cases, &match_pair](std::size_t i) {
return match_pair(i, 1) && (
cases.empty() || (cases[i + 1] == (cases[i] + 1))
);

View File

@ -146,7 +146,7 @@ OSTD_UNIT_TEST {
namespace detail {
template<typename R, typename C>
static void insort(R range, C &compare) {
inline void insort(R range, C &compare) {
range_size_t<R> rlen = range.size();
for (range_size_t<R> i = 1; i < rlen; ++i) {
range_size_t<R> j = i;
@ -160,7 +160,7 @@ namespace detail {
}
template<typename R, typename C>
static void hs_sift_down(
inline void hs_sift_down(
R range, range_size_t<R> s, range_size_t<R> e, C &compare
) {
range_size_t<R> r = s;
@ -184,7 +184,7 @@ namespace detail {
}
template<typename R, typename C>
static void heapsort(R range, C &compare) {
inline void heapsort(R range, C &compare) {
range_size_t<R> len = range.size();
range_size_t<R> st = (len - 2) / 2;
for (;;) {
@ -203,7 +203,7 @@ namespace detail {
}
template<typename R, typename C>
static void introloop(R range, C &compare, range_size_t<R> depth) {
inline void introloop(R range, C &compare, range_size_t<R> depth) {
using std::swap;
if (range.size() <= 10) {
detail::insort(range, compare);
@ -594,7 +594,7 @@ inline auto none_of(Predicate &&pred) {
* Iterates the range and as soon as `range.front()` is equal to `v`,
* returns `range`. The `range` is at least ostd::input_range_tag.
*
* @sse ostd::find_last(), ostd::find_if(), ostd::find_if_not(),
* @see ostd::find_last(), ostd::find_if(), ostd::find_if_not(),
* ostd::find_one_of()
*/
template<typename InputRange, typename Value>
@ -625,7 +625,7 @@ inline auto find(Value &&v) {
* the previous result of ostd::find() in case nothing is found next, this
* algortihm requires `range` to be at least ostd::forward_range_tag.
*
* @sse ostd::find(), ostd::find_if(), ostd::find_if_not(),
* @see ostd::find(), ostd::find_if(), ostd::find_if_not(),
* ostd::find_one_of()
*/
template<typename ForwardRange, typename Value>
@ -661,7 +661,7 @@ inline auto find_last(Value &&v) {
* Iterates the range and as soon as `pred(range.front())` is true,
* returns `range`. The `range` is at least ostd::input_range_tag.
*
* @sse ostd::find(), ostd::find_last(), ostd::find_if_not(),
* @see ostd::find(), ostd::find_last(), ostd::find_if_not(),
* ostd::find_one_of()
*/
template<typename InputRange, typename Predicate>
@ -690,7 +690,7 @@ inline auto find_if(Predicate &&pred) {
* Iterates the range and as soon as `!pred(range.front())` is true,
* returns `range`. The `range` is at least ostd::input_range_tag.
*
* @sse ostd::find(), ostd::find_last(), ostd::find_if(), ostd::find_one_of()
* @see ostd::find(), ostd::find_last(), ostd::find_if(), ostd::find_one_of()
*/
template<typename InputRange, typename Predicate>
inline InputRange find_if_not(InputRange range, Predicate pred) {
@ -729,7 +729,7 @@ inline auto find_if_not(Predicate &&pred) {
* Use ostd::find_one_of() if you want to use the `==` operator
* instead of calling `compare`.
*
* @sse ostd::find(), ostd::find_last(), ostd::find_if(), ostd::find_if_not(),
* @see ostd::find(), ostd::find_last(), ostd::find_if(), ostd::find_if_not(),
* ostd::find_one_of()
*/
template<typename InputRange, typename ForwardRange, typename Compare>
@ -779,7 +779,7 @@ inline auto find_one_of_cmp(ForwardRange &&values, Compare &&compare) {
* Use ostd::find_one_of_cmp() if you want to use a comparison
* function instead of the `==` operator.
*
* @sse ostd::find(), ostd::find_last(), ostd::find_if(), ostd::find_if_not(),
* @see ostd::find(), ostd::find_last(), ostd::find_if(), ostd::find_if_not(),
* ostd::find_one_of_cmp()
*/
template<typename InputRange, typename ForwardRange>

View File

@ -492,7 +492,7 @@ private:
case arg_value::OPTIONAL:
case arg_value::ALL:
break;
default:
case arg_value::REST:
throw arg_error{"invalid argument requirement"};
}
}
@ -917,7 +917,6 @@ protected:
private:
std::string p_name, p_title;
std::vector<std::unique_ptr<arg_description>> p_opts;
};
template<typename F>
@ -959,9 +958,6 @@ inline bool arg_description_container::for_each(
return false;
}
break;
default:
/* should never happen */
throw arg_error{"invalid argument type"};
}
}
return true;
@ -1519,8 +1515,8 @@ struct default_help_formatter {
/** @brief Formats the options (after usage line).
*
* Positional arguments not belonging to any group are formatted
* first, with `\nPositional arguments:\n` header. Same goes with
* optional arguments, except with `\nOptional arguments:\n`.
* first, with `\\nPositional arguments:\\n` header. Same goes with
* optional arguments, except with `\\nOptional arguments:\\n`.
*
* If either positional or optional arguments without group don't
* exist, the section is skipped.
@ -1529,7 +1525,7 @@ struct default_help_formatter {
* help strings are aligned and offset by 2 spaces from the longest
* argument string.
*
* Group titles are formatted as `\nTITLE:\n`.
* Group titles are formatted as `\\nTITLE:\\n`.
*
* Within groups, positional arguments come first and optional
* arguments second. Mutually exclusive groups are expanded.
@ -1586,8 +1582,6 @@ struct default_help_formatter {
}
);
break;
default:
break;
}
return true;
}, false, false);
@ -1636,9 +1630,7 @@ struct default_help_formatter {
}
auto &garg = static_cast<arg_group const &>(arg);
format(out, "\n%s:\n", garg.title());
garg.for_each([
&write_help, &out, &allopt, &allpos
](auto const &marg) {
garg.for_each([&allopt, &allpos](auto const &marg) {
switch (marg.type()) {
case arg_type::OPTIONAL:
allopt.push_back(
@ -1650,7 +1642,8 @@ struct default_help_formatter {
static_cast<arg_positional const *>(&marg)
);
break;
default:
case arg_type::GROUP:
case arg_type::MUTUALLY_EXCLUSIVE_GROUP:
/* should never happen */
throw arg_error{"invalid argument type"};
}
@ -1700,7 +1693,7 @@ struct default_help_formatter {
}
format(out, " [%s ...]", mt);
break;
default:
case arg_value::REST:
break;
}
names.pop_front();
@ -1741,7 +1734,8 @@ struct default_help_formatter {
case arg_type::POSITIONAL:
format_option(out, static_cast<arg_positional const &>(arg));
break;
default:
case arg_type::GROUP:
case arg_type::MUTUALLY_EXCLUSIVE_GROUP:
/* should never happen */
throw arg_error{"invalid argument type"};
}
@ -1767,7 +1761,7 @@ inline auto arg_print_help(OutputRange o, arg_parser &p) {
p.print_help(o);
p.stop_parsing();
};
};
}
/** @brief Like ostd::arg_print_help() with ostd::cout. */
inline auto arg_print_help(arg_parser &p) {

View File

@ -34,6 +34,35 @@ namespace ostd {
* @{
*/
struct coroutine_context;
namespace detail {
/* from boost.fcontext */
using fcontext_t = void *;
struct transfer_t {
fcontext_t ctx;
void *data;
};
extern "C" OSTD_EXPORT
transfer_t OSTD_CDECL ostd_jump_fcontext(
fcontext_t const to, void *vp
);
extern "C" OSTD_EXPORT
fcontext_t OSTD_CDECL ostd_make_fcontext(
void *sp, std::size_t size, void (*fn)(transfer_t)
);
extern "C" OSTD_EXPORT
transfer_t OSTD_CDECL ostd_ontop_fcontext(
fcontext_t const to, void *vp, transfer_t (*fn)(transfer_t)
);
OSTD_EXPORT extern thread_local coroutine_context *coro_current;
} /* namespace detail */
/** @brief An allocated stack.
*
* This represents a stack allocated by a stack allocator. It doesn't

View File

@ -58,35 +58,6 @@ struct coroutine_error: std::runtime_error {
using std::runtime_error::runtime_error;
};
struct coroutine_context;
namespace detail {
/* from boost.fcontext */
using fcontext_t = void *;
struct transfer_t {
fcontext_t ctx;
void *data;
};
extern "C" OSTD_EXPORT
transfer_t OSTD_CDECL ostd_jump_fcontext(
fcontext_t const to, void *vp
);
extern "C" OSTD_EXPORT
fcontext_t OSTD_CDECL ostd_make_fcontext(
void *sp, std::size_t size, void (*fn)(transfer_t)
);
extern "C" OSTD_EXPORT
transfer_t OSTD_CDECL ostd_ontop_fcontext(
fcontext_t const to, void *vp, transfer_t (*fn)(transfer_t)
);
OSTD_EXPORT extern thread_local coroutine_context *coro_current;
} /* namespace detail */
/** @brief An encapsulated context any coroutine-type inherits from.
*
* Internally, this provides some basic infrastructure for creating and
@ -135,7 +106,7 @@ protected:
*/
coroutine_context(coroutine_context &&c):
p_stack(std::move(c.p_stack)), p_coro(c.p_coro), p_orig(c.p_orig),
p_except(std::move(c.p_except)), p_state(c.p_state), p_free(c.p_free)
p_free(c.p_free), p_except(std::move(c.p_except)), p_state(c.p_state)
{
c.p_coro = c.p_orig = nullptr;
c.p_stack = { nullptr, 0 };
@ -249,9 +220,9 @@ protected:
swap(p_stack, other.p_stack);
swap(p_coro, other.p_coro);
swap(p_orig, other.p_orig);
swap(p_free, other.p_free);
swap(p_except, other.p_except);
swap(p_state, other.p_state);
swap(p_free, other.p_free);
}
/** @brief Allocates a stack and creates a context.
@ -276,10 +247,10 @@ protected:
p_stack = sa.allocate();
void *sp = get_stack_ptr<SA>();
std::size_t asize = p_stack.size - (
auto asize = std::size_t(p_stack.size - std::size_t(
static_cast<unsigned char *>(p_stack.ptr) -
static_cast<unsigned char *>(sp)
);
));
p_coro = detail::ostd_make_fcontext(sp, asize, &context_call<C, SA>);
new (sp) SA(std::move(sa));
@ -374,9 +345,9 @@ release:
stack_context p_stack;
detail::fcontext_t p_coro = nullptr;
detail::fcontext_t p_orig = nullptr;
void (*p_free)(void *) = nullptr;
std::exception_ptr p_except;
state p_state = state::HOLD;
void (*p_free)(void *) = nullptr;
};
template<typename T>
@ -653,7 +624,7 @@ namespace detail {
* as they were passed, exactly as if they were passed as regular args.
*
* @tparam R The return template type.
* @tparam A... The argument template types.
* @tparam A The argument template types.
*/
template<typename R, typename ...A>
struct coroutine<R(A...)>: coroutine_context {

View File

@ -134,7 +134,7 @@ namespace detail {
* 7 .. string
* 8 .. custom object
*/
inline constexpr unsigned char const fmt_specs[] = {
static inline constexpr unsigned char const fmt_specs[] = {
/* uppercase spec set */
1, 3, 8, 8, /* A B C D */
1, 1, 1, 8, /* E F G H */
@ -160,12 +160,12 @@ namespace detail {
0, 0, 0, 0, 0
};
inline constexpr int const fmt_bases[] = {
static inline constexpr int const fmt_bases[] = {
0, 0, 0, 2, 8, 10, 16, 0
};
/* non-printable escapes up to 0x20 (space) */
inline constexpr char const *fmt_escapes[] = {
static inline constexpr char const *fmt_escapes[] = {
"\\0" , "\\x01", "\\x02", "\\x03", "\\x04", "\\x05",
"\\x06", "\\a" , "\\b" , "\\t" , "\\n" , "\\v" ,
"\\f" , "\\r" , "\\x0E", "\\x0F", "\\x10", "\\x11",
@ -215,33 +215,35 @@ namespace detail {
* pair, array, possibly other types added later or overridden...
*/
template<typename T>
std::true_type tuple_like_test(typename std::tuple_size<T>::type *);
inline std::true_type tuple_like_test(typename std::tuple_size<T>::type *);
template<typename>
std::false_type tuple_like_test(...);
inline std::false_type tuple_like_test(...);
template<typename T>
inline constexpr bool is_tuple_like = decltype(tuple_like_test<T>(0))::value;
static inline constexpr bool is_tuple_like =
decltype(tuple_like_test<T>(0))::value;
/* character type tests */
template<typename C>
inline constexpr bool is_character = std::is_same_v<C, char> ||
std::is_same_v<C, wchar_t> ||
std::is_same_v<C, char16_t> ||
std::is_same_v<C, char32_t>;
static inline constexpr bool is_character = std::is_same_v<C, char> ||
std::is_same_v<C, wchar_t> ||
std::is_same_v<C, char16_t> ||
std::is_same_v<C, char32_t>;
/* test if format traits are available for the type */
template<typename T, typename R>
static std::true_type test_tofmt(decltype(format_traits<T>::to_format(
inline std::true_type test_tofmt(decltype(format_traits<T>::to_format(
std::declval<T const &>(), std::declval<R &>(),
std::declval<format_spec const &>()
)) *);
template<typename, typename>
static std::false_type test_tofmt(...);
inline std::false_type test_tofmt(...);
template<typename T, typename R>
inline constexpr bool fmt_tofmt_test = decltype(test_tofmt<T, R>(0))::value;
static inline constexpr bool fmt_tofmt_test =
decltype(test_tofmt<T, R>(0))::value;
template<typename C, typename F>
inline int ac_to_mb(C c, F const &f, char *buf) {
@ -252,7 +254,7 @@ namespace detail {
if (ret != std::codecvt_base::ok) {
return -1;
}
return ton - &buf[0];
return int(ton - &buf[0]);
}
inline int wc_to_mb_loc(wchar_t c, char *buf, std::locale const &loc) {
@ -847,14 +849,16 @@ private:
if (p.front() == need) {
p_is_tuple = tuple;
if (tuple) {
p_nested = begin_inner.slice(0, &p[0] - &begin_inner[0] - 1);
p_nested = begin_inner.slice(
0, std::size_t(&p[0] - &begin_inner[0] - 1)
);
p_nested_sep = nullptr;
} else {
p_nested = begin_inner.slice(
0, &begin_delim[0] - &begin_inner[0]
0, std::size_t(&begin_delim[0] - &begin_inner[0])
);
p_nested_sep = begin_delim.slice(
0, &p[0] - &begin_delim[0] - 1
0, std::size_t(&p[0] - &begin_delim[0] - 1)
);
}
p.pop_front();
@ -864,14 +868,16 @@ private:
}
/* found actual delimiter start... */
if ((p.front() == '|') && !tuple) {
p_nested = begin_inner.slice(0, &p[0] - &begin_inner[0] - 1);
p_nested = begin_inner.slice(
0, std::size_t(&p[0] - &begin_inner[0] - 1)
);
p.pop_front();
p_nested_sep = p;
for (p = find(p, '%'); !p.empty(); p = find(p, '%')) {
p.pop_front();
if (p.front() == ')') {
p_nested_sep = p_nested_sep.slice(
0, &p[0] - &p_nested_sep[0] - 1
0, std::size_t(&p[0] - &p_nested_sep[0] - 1)
);
p.pop_front();
p_fmt = p;
@ -1083,15 +1089,15 @@ private:
throw format_error{"cannot format integers with the given spec"};
}
/* 32 for lowercase variants, 0 for uppercase */
int cmask = ((isp >= 'a') << 5);
char cmask = char((isp >= 'a') << 5);
int base = detail::fmt_bases[specn];
T base = T(detail::fmt_bases[specn]);
if (!val) {
ndig = 1;
buf[0] = '0';
} else {
for (; val; val /= base) {
T vb = val % base;
auto vb = char(val % base);
buf[ndig++] = (vb + "70"[vb < 10]) | cmask;
}
}
@ -1132,7 +1138,7 @@ private:
}
++grpp;
}
total += nseps * ntsep;
total += nseps * std::size_t(ntsep);
}
/* here ends the bullshit */
@ -1244,7 +1250,8 @@ private:
fmt_num_put<R> nump;
nump.put(
fmt_out<R>{&writer, &p_loc}, st,
(p_flags & FMT_FLAG_ZERO) ? L'0' : L' ', val
(p_flags & FMT_FLAG_ZERO) ? L'0' : L' ',
std::conditional_t<std::is_same_v<T, long double>, T, double>(val)
);
}
@ -1291,10 +1298,10 @@ private:
throw format_error{"tuples need the '%s' spec"};
}
writer.put('{');
write_range_val(writer, [&writer, escape, this](auto const &rval) {
format_spec sp{'s', p_loc, escape ? FMT_FLAG_AT : 0};
write_range_val(writer, [&writer, this](auto const &rval, bool esc) {
format_spec sp{'s', p_loc, esc ? FMT_FLAG_AT : 0};
sp.write_arg(writer, 0, rval);
}, ", ", val);
}, ", ", val, escape);
writer.put('}');
return;
}
@ -1369,13 +1376,11 @@ private:
) const {
if constexpr(detail::is_tuple_like<T>) {
if (expandval) {
std::apply([&writer, escape, &fmt, this](
auto const &...args
) mutable {
std::apply([
this, &writer, &fmt, flags = escape ? FMT_FLAG_AT : 0
](auto const &...args) mutable {
format_spec sp{fmt, p_loc};
if (escape) {
sp.p_gflags |= FMT_FLAG_AT;
}
sp.p_gflags |= flags;
sp.write_fmt(writer, args...);
}, item);
return;
@ -1388,9 +1393,10 @@ private:
sp.write_fmt(writer, item);
}
template<typename R, typename F, typename T>
template<typename R, typename F, typename T, typename ...A>
void write_range_val(
R &writer, F &&func, [[maybe_unused]] string_range sep, T const &val
R &writer, F &&func, [[maybe_unused]] string_range sep, T const &val,
A const &...args
) const {
if constexpr(detail::iterable_test<T>) {
auto range = ostd::iter(val);
@ -1398,7 +1404,7 @@ private:
return;
}
for (;;) {
func(range.front());
func(range.front(), args...);
range.pop_front();
if (range.empty()) {
break;
@ -1424,13 +1430,12 @@ private:
}
} else {
write_range_val(writer, [
this, &writer, escape = p_gflags & FMT_FLAG_AT, expandval,
fmt = rest()
](auto const &rval) {
fmt = rest(), this, &writer
](auto const &rval, bool expval, bool escape) {
this->write_range_item(
writer, escape, expandval, fmt, rval
writer, escape, expval, fmt, rval
);
}, sep, val);
}, sep, val, expandval, p_gflags & FMT_FLAG_AT);
}
}
@ -1458,7 +1463,7 @@ private:
}
} else {
if constexpr(detail::is_tuple_like<T>) {
std::apply([this, &writer, &val](auto const &...vals) mutable {
std::apply([this, &writer](auto const &...vals) mutable {
this->write_fmt(writer, vals...);
}, val);
} else {

View File

@ -110,7 +110,37 @@ struct OSTD_EXPORT subprocess {
private:
struct nat {};
std::aligned_storage_t<2 * sizeof(void *), alignof(void *)> p_data;
void *p_current = nullptr;
public:
/** @brief The standard input stream when redirected.
*
* If no redirection is done (see ostd::subprocess::use_in) then
* this stream will not be opened.
*
* @see ostd::subprocess::out, ostd::subprocess::err
*/
file_stream in = file_stream{};
/** @brief The standard output stream when redirected.
*
* If no redirection is done (see ostd::subprocess::use_out) then
* this stream will not be opened.
*
* @see ostd::subprocess::in, ostd::subprocess::err
*/
file_stream out = file_stream{};
/** @brief The standard error stream when redirected.
*
* If no redirection is done (see ostd::subprocess::use_err) then
* this stream will not be opened.
*
* @see ostd::subprocess::in, ostd::subprocess::out
*/
file_stream err = file_stream{};
/** @brief The standard input redirection mode.
*
* The value is one of ostd::subprocess_stream. Set this before opening
@ -154,33 +184,6 @@ public:
*/
subprocess_stream use_err = subprocess_stream::DEFAULT;
/** @brief The standard input stream when redirected.
*
* If no redirection is done (see ostd::subprocess::use_in) then
* this stream will not be opened.
*
* @see ostd::subprocess::out, ostd::subprocess::err
*/
file_stream in = file_stream{};
/** @brief The standard output stream when redirected.
*
* If no redirection is done (see ostd::subprocess::use_out) then
* this stream will not be opened.
*
* @see ostd::subprocess::in, ostd::subprocess::err
*/
file_stream out = file_stream{};
/** @brief The standard error stream when redirected.
*
* If no redirection is done (see ostd::subprocess::use_err) then
* this stream will not be opened.
*
* @see ostd::subprocess::in, ostd::subprocess::out
*/
file_stream err = file_stream{};
/** @brief Initializes the structure with the given stream redirections. */
subprocess(
subprocess_stream in_use = subprocess_stream::DEFAULT,
@ -232,8 +235,8 @@ public:
/** @brief Moves the subprocess data. */
subprocess(subprocess &&i) noexcept:
use_in(i.use_in), use_out(i.use_out), use_err(i.use_err),
in(std::move(i.in)), out(std::move(i.out)), err(std::move(i.err))
in(std::move(i.in)), out(std::move(i.out)), err(std::move(i.err)),
use_in(i.use_in), use_out(i.use_out), use_err(i.use_err)
{
move_data(i);
}
@ -460,9 +463,6 @@ private:
void reset();
void move_data(subprocess &i);
void swap_data(subprocess &i);
std::aligned_storage_t<2 * sizeof(void *)> p_data;
void *p_current = nullptr;
};
/** @} */

View File

@ -186,7 +186,8 @@ namespace detail {
};
template<typename R>
inline constexpr bool test_range_category = range_category_test<R>::value;
static inline constexpr bool const test_range_category =
range_category_test<R>::value;
template<typename R, bool, bool>
struct range_traits_base {
@ -199,7 +200,7 @@ namespace detail {
};
template<typename R>
inline constexpr bool test_elem_reference =
static inline constexpr bool const test_elem_reference =
std::is_convertible_v<typename R::range_category, input_range_tag> &&
std::is_lvalue_reference_v<typename R::reference> &&
std::is_same_v<
@ -388,7 +389,7 @@ using range_reference_t = typename range_traits<R>::reference;
*
*/
template<typename R1, typename R2>
inline constexpr bool is_range_element_swappable_with =
static inline constexpr bool const is_range_element_swappable_with =
range_traits<R1>::template is_element_swappable_with<R2>;
/** @brief Checks whether a range can swap elements within itself.
@ -401,7 +402,7 @@ inline constexpr bool is_range_element_swappable_with =
*
*/
template<typename R>
inline constexpr bool is_range_element_swappable =
static inline constexpr bool const is_range_element_swappable =
range_traits<R>::is_element_swappable;
/** @brief Checks whether two ranges can nothrow swap elements with each other.
@ -414,7 +415,7 @@ inline constexpr bool is_range_element_swappable =
*
*/
template<typename R1, typename R2>
inline constexpr bool is_range_element_nothrow_swappable_with =
static inline constexpr bool const is_range_element_nothrow_swappable_with =
range_traits<R1>::template is_element_nothrow_swappable_with<R2>;
/** @brief Checks whether a range can nothrow swap elements within itself.
@ -427,21 +428,21 @@ inline constexpr bool is_range_element_nothrow_swappable_with =
*
*/
template<typename R>
inline constexpr bool is_range_element_nothrow_swappable =
static inline constexpr bool const is_range_element_nothrow_swappable =
range_traits<R>::is_element_nothrow_swappable;
// is input range
namespace detail {
template<typename T>
inline constexpr bool is_input_range_core =
static inline constexpr bool const is_input_range_core =
std::is_convertible_v<range_category_t<T>, input_range_tag>;
template<typename T, bool = detail::test_range_category<T>>
inline constexpr bool is_input_range_base = false;
static inline constexpr bool const is_input_range_base = false;
template<typename T>
inline constexpr bool is_input_range_base<T, true> =
static inline constexpr bool const is_input_range_base<T, true> =
detail::is_input_range_core<T>;
}
@ -453,20 +454,21 @@ namespace detail {
* @see ostd::is_forward_range, ostd::is_output_range
*/
template<typename T>
inline constexpr bool is_input_range = detail::is_input_range_base<T>;
static inline constexpr bool const is_input_range =
detail::is_input_range_base<T>;
// is forward range
namespace detail {
template<typename T>
inline constexpr bool is_forward_range_core =
static inline constexpr bool const is_forward_range_core =
std::is_convertible_v<range_category_t<T>, forward_range_tag>;
template<typename T, bool = detail::test_range_category<T>>
inline constexpr bool is_forward_range_base = false;
static inline constexpr bool const is_forward_range_base = false;
template<typename T>
inline constexpr bool is_forward_range_base<T, true> =
static inline constexpr bool const is_forward_range_base<T, true> =
detail::is_forward_range_core<T>;
}
@ -478,20 +480,21 @@ namespace detail {
* @see ostd::is_input_range, ostd::is_bidirectional_range
*/
template<typename T>
inline constexpr bool is_forward_range = detail::is_forward_range_base<T>;
static inline constexpr bool const is_forward_range =
detail::is_forward_range_base<T>;
// is bidirectional range
namespace detail {
template<typename T>
inline constexpr bool is_bidirectional_range_core =
static inline constexpr bool const is_bidirectional_range_core =
std::is_convertible_v<range_category_t<T>, bidirectional_range_tag>;
template<typename T, bool = detail::test_range_category<T>>
inline constexpr bool is_bidirectional_range_base = false;
static inline constexpr bool const is_bidirectional_range_base = false;
template<typename T>
inline constexpr bool is_bidirectional_range_base<T, true> =
static inline constexpr bool const is_bidirectional_range_base<T, true> =
detail::is_bidirectional_range_core<T>;
}
@ -503,21 +506,21 @@ namespace detail {
* @see ostd::is_forward_range, ostd::is_random_access_range
*/
template<typename T>
inline constexpr bool is_bidirectional_range =
static inline constexpr bool const is_bidirectional_range =
detail::is_bidirectional_range_base<T>;
// is random access range
namespace detail {
template<typename T>
inline constexpr bool is_random_access_range_core =
static inline constexpr bool const is_random_access_range_core =
std::is_convertible_v<range_category_t<T>, random_access_range_tag>;
template<typename T, bool = detail::test_range_category<T>>
inline constexpr bool is_random_access_range_base = false;
static inline constexpr bool const is_random_access_range_base = false;
template<typename T>
inline constexpr bool is_random_access_range_base<T, true> =
static inline constexpr bool const is_random_access_range_base<T, true> =
detail::is_random_access_range_core<T>;
}
@ -530,21 +533,21 @@ namespace detail {
* @see ostd::is_bidirectional_range, ostd::is_finite_random_access_range
*/
template<typename T>
inline constexpr bool is_random_access_range =
static inline constexpr bool const is_random_access_range =
detail::is_random_access_range_base<T>;
// is finite random access range
namespace detail {
template<typename T>
inline constexpr bool is_finite_random_access_range_core =
static inline constexpr bool const is_finite_random_access_range_core =
std::is_convertible_v<range_category_t<T>, finite_random_access_range_tag>;
template<typename T, bool = detail::test_range_category<T>>
inline constexpr bool is_finite_random_access_range_base = false;
static inline constexpr bool const is_finite_random_access_range_base = false;
template<typename T>
inline constexpr bool is_finite_random_access_range_base<T, true> =
static inline constexpr bool const is_finite_random_access_range_base<T, true> =
detail::is_finite_random_access_range_core<T>;
}
@ -557,21 +560,21 @@ namespace detail {
* @see ostd::is_random_access_range, ostd::is_contiguous_range
*/
template<typename T>
inline constexpr bool is_finite_random_access_range =
static inline constexpr bool const is_finite_random_access_range =
detail::is_finite_random_access_range_base<T>;
// is contiguous range
namespace detail {
template<typename T>
inline constexpr bool is_contiguous_range_core =
static inline constexpr bool const is_contiguous_range_core =
std::is_convertible_v<range_category_t<T>, contiguous_range_tag>;
template<typename T, bool = detail::test_range_category<T>>
inline constexpr bool is_contiguous_range_base = false;
static inline constexpr bool const is_contiguous_range_base = false;
template<typename T>
inline constexpr bool is_contiguous_range_base<T, true> =
static inline constexpr bool const is_contiguous_range_base<T, true> =
detail::is_contiguous_range_core<T>;
}
@ -582,25 +585,26 @@ namespace detail {
* @see ostd::is_finite_random_access_range
*/
template<typename T>
inline constexpr bool is_contiguous_range = detail::is_contiguous_range_base<T>;
static inline constexpr bool const is_contiguous_range =
detail::is_contiguous_range_base<T>;
// is output range
namespace detail {
template<typename R, typename T>
static std::true_type test_outrange(typename std::is_same<
inline std::true_type test_outrange(typename std::is_same<
decltype(std::declval<R &>().put(std::declval<T>())), void
>::type *);
template<typename, typename>
static std::false_type test_outrange(...);
inline std::false_type test_outrange(...);
template<typename R, typename T>
inline constexpr bool output_range_test =
static inline constexpr bool const output_range_test =
decltype(test_outrange<R, T>())::value;
template<typename T>
inline constexpr bool is_output_range_core =
static inline constexpr bool const is_output_range_core =
std::is_convertible_v<range_category_t<T>, output_range_tag> || (
is_input_range<T> && (
output_range_test<T, range_value_t<T> const &> ||
@ -610,10 +614,10 @@ namespace detail {
);
template<typename T, bool = detail::test_range_category<T>>
inline constexpr bool is_output_range_base = false;
static inline constexpr bool const is_output_range_base = false;
template<typename T>
inline constexpr bool is_output_range_base<T, true> =
static inline constexpr bool const is_output_range_base<T, true> =
detail::is_output_range_core<T>;
}
@ -627,7 +631,8 @@ namespace detail {
* @see ostd::is_input_range
*/
template<typename T>
inline constexpr bool is_output_range = detail::is_output_range_base<T>;
static inline constexpr bool const is_output_range =
detail::is_output_range_base<T>;
namespace detail {
// range iterator
@ -1203,28 +1208,28 @@ inline auto zip(R1 &&r1, R &&...rr) {
namespace detail {
template<typename C>
static std::true_type test_direct_iter(
inline std::true_type test_direct_iter(
decltype(std::declval<C &>().iter()) *
);
template<typename>
static std::false_type test_direct_iter(...);
inline std::false_type test_direct_iter(...);
template<typename C>
inline constexpr bool direct_iter_test =
static inline constexpr bool const direct_iter_test =
decltype(test_direct_iter<C>(0))::value;
template<typename C>
static std::true_type test_std_iter(
inline std::true_type test_std_iter(
decltype(std::begin(std::declval<C &>())) *,
decltype(std::end(std::declval<C &>())) *
);
template<typename>
static std::false_type test_std_iter(...);
inline std::false_type test_std_iter(...);
template<typename C>
inline constexpr bool std_iter_test =
static inline constexpr bool const std_iter_test =
decltype(test_std_iter<C>(0, 0))::value;
/* direct iter and std iter; the case for std iter is
@ -1298,14 +1303,15 @@ inline auto citer(T const &r) -> decltype(ranged_traits<T const>::iter(r)) {
namespace detail {
template<typename T>
static std::true_type test_iterable(
inline std::true_type test_iterable(
decltype(ostd::iter(std::declval<T>())) *
);
template<typename>
static std::false_type test_iterable(...);
inline std::false_type test_iterable(...);
template<typename T>
inline constexpr bool iterable_test = decltype(test_iterable<T>(0))::value;
static inline constexpr bool const iterable_test =
decltype(test_iterable<T>(0))::value;
}
namespace detail {
@ -1387,7 +1393,7 @@ OSTD_UNIT_TEST {
fail_if(r.empty() || (r.front() != 9));
r.pop_front();
fail_if(!r.empty());
};
}
#endif
namespace detail {
@ -1894,7 +1900,8 @@ struct iterator_range: input_range<iterator_range<T>> {
* If the indexes are not within bounds, the behavior is undefined.
*/
iterator_range slice(size_type start, size_type end) const {
return iterator_range(p_beg + start, p_beg + end);
using DT = typename std::iterator_traits<T>::difference_type;
return iterator_range(p_beg + DT(start), p_beg + DT(end));
}
/** @brief Slices the range with size() for the second argument.
@ -1911,7 +1918,10 @@ struct iterator_range: input_range<iterator_range<T>> {
* Only valid if the range is at least finite random access.
* If the index is not within bounds, the behavior is undefined.
*/
reference operator[](size_type i) const { return p_beg[i]; }
reference operator[](size_type i) const {
using DT = typename std::iterator_traits<T>::difference_type;
return p_beg[DT(i)];
}
/** @brief Gets the pointer to the first element.
*

View File

@ -567,6 +567,13 @@ struct stream_range<T, true>: input_range<stream_range<T>> {
p_stream(r.p_stream), p_item(r.p_item)
{}
/** @brief Stream ranges can be copied, the cached value is also copied. */
stream_range &operator=(stream_range const &r) {
p_stream = r.p_stream;
p_item = r.p_item;
return *this;
}
/** @brief Checks if the range (stream) is empty.
*
* If there is a value cached in this range, this returns false.

View File

@ -92,7 +92,7 @@ private:
public:
/** @brief Constructs an empty slice. */
basic_char_range() noexcept: p_beg(nullptr), p_end(nullptr) {};
basic_char_range() noexcept: p_beg(nullptr), p_end(nullptr) {}
/** @brief Constructs a slice from two pointers.
*
@ -108,6 +108,11 @@ public:
p_beg(nullptr), p_end(nullptr)
{}
/** @brief Slices are arbitrarily copy constructible. */
basic_char_range(basic_char_range const &v) noexcept:
p_beg(v.p_beg), p_end(v.p_end)
{}
/** @brief Constructs a slice from a pointer or a static array.
*
* This constructor handles two cases. The input must be convertible
@ -232,7 +237,7 @@ public:
reference back() const noexcept { return *(p_end - 1); }
/** @brief Gets the number of value_type in the slice. */
size_type size() const noexcept { return p_end - p_beg; }
size_type size() const noexcept { return size_type(p_end - p_beg); }
/** @brief Gets the number of code points in the slice.
*
@ -319,7 +324,7 @@ public:
int compare(basic_char_range<value_type const> s) const noexcept {
size_type s1 = size(), s2 = s.size();
for (size_type i = 0, ms = std::min(s1, s2); i < ms; ++i) {
int d = p_beg[i] - s[i];
int d = int(p_beg[i]) - int(s[i]);
if (d) {
return d;
}
@ -859,7 +864,7 @@ namespace utf {
p_current = -1;
throw utf_error{"UTF-8 decoding failed"};
} else {
p_current = ret;
p_current = std::int32_t(ret);
}
}

View File

@ -46,9 +46,9 @@ namespace test {
#define OSTD_TEST_MODULE_CURRENT OSTD_TEST_MODULE_STR(OSTD_BUILD_TESTS)
namespace detail {
static std::vector<void (*)()> test_cases;
static inline std::vector<void (*)()> test_cases;
static bool add_test(std::string testn, void (*func)()) {
inline bool add_test(std::string testn, void (*func)()) {
if (testn == OSTD_TEST_MODULE_CURRENT) {
test_cases.push_back(func);
}
@ -73,13 +73,13 @@ namespace detail {
* after including any headers and undefined at the end of the file.
*/
#define OSTD_UNIT_TEST \
static void OSTD_TEST_FUNC_NAME(test_func, OSTD_TEST_MODULE, __LINE__)(); \
static bool OSTD_TEST_FUNC_NAME(test_case, OSTD_TEST_MODULE, __LINE__) = \
inline void OSTD_TEST_FUNC_NAME(test_func, OSTD_TEST_MODULE, __LINE__)(); \
static inline bool OSTD_TEST_FUNC_NAME(test_case, OSTD_TEST_MODULE, __LINE__) = \
ostd::test::detail::add_test( \
OSTD_TEST_MODULE_STR(OSTD_TEST_MODULE), \
&OSTD_TEST_FUNC_NAME(test_func, OSTD_TEST_MODULE, __LINE__) \
); \
static void OSTD_TEST_FUNC_NAME(test_func, OSTD_TEST_MODULE, __LINE__)()
inline void OSTD_TEST_FUNC_NAME(test_func, OSTD_TEST_MODULE, __LINE__)()
/** @brief Makes the test fail if the given value is true.
*
@ -90,7 +90,7 @@ static void OSTD_TEST_FUNC_NAME(test_func, OSTD_TEST_MODULE, __LINE__)()
*
* @see ostd::test::fail(), ostd::test::fail_if_not()
*/
void fail_if(bool b) {
inline void fail_if(bool b) {
if (b) {
throw detail::test_error{};
}
@ -100,7 +100,7 @@ void fail_if(bool b) {
*
* The test will fail if the given value is false.
*/
void fail_if_not(bool b) {
inline void fail_if_not(bool b) {
if (!b) {
throw detail::test_error{};
}
@ -112,7 +112,7 @@ void fail_if_not(bool b) {
*
* @see ostd::test::fail_if()
*/
void fail() {
[[noreturn]] inline void fail() {
throw detail::test_error{};
}
@ -121,7 +121,7 @@ void fail() {
* @returns An std::pair containing the number of tests that succeeded
* as the first value and failed as the second value.
*/
std::pair<std::size_t, std::size_t> run() {
inline std::pair<std::size_t, std::size_t> run() {
std::size_t succ = 0, fail = 0;
for (auto &f: detail::test_cases) {
try {

View File

@ -40,7 +40,7 @@ namespace detail {
OSTD_EXPORT void *stack_alloc(std::size_t sz) {
if constexpr(CONTEXT_USE_MMAP) {
void *p = mmap(
0, sz, PROT_READ | PROT_WRITE,
nullptr, sz, PROT_READ | PROT_WRITE,
MAP_PRIVATE | CONTEXT_MAP_ANON, -1, 0
);
if (p == MAP_FAILED) {

View File

@ -47,7 +47,7 @@ namespace detail {
ret = (ret << 6) | bch;
}
/* number of continuation bytes */
std::size_t n = sr.data() - r.data() - 1;
auto n = sr.data() - r.data() - 1;
/* invalid sequence - too many continuation bits */
if (n > 3) {
return false;
@ -71,12 +71,12 @@ namespace detail {
std::uint8_t (&ret)[4], std::uint32_t ch
) noexcept {
if (ch <= 0x7F) {
ret[0] = ch;
ret[0] = std::uint8_t(ch);
return 1;
}
if (ch <= 0x7FF) {
ret[0] = 0xC0 | (ch >> 6);
ret[1] = 0x80 | (ch & 0x3F);
ret[0] = std::uint8_t(0xC0 | (ch >> 6));
ret[1] = std::uint8_t(0x80 | (ch & 0x3F));
return 2;
}
if (ch <= 0xFFFF) {
@ -86,16 +86,16 @@ namespace detail {
if ((ch >= 0xD800) && (ch <= 0xDFFF)) {
return 0;
}
ret[0] = 0xE0 | (ch >> 12);
ret[1] = 0x80 | ((ch >> 6) & 0x3F);
ret[2] = 0x80 | (ch & 0x3F);
ret[0] = std::uint8_t(0xE0 | (ch >> 12));
ret[1] = std::uint8_t(0x80 | ((ch >> 6) & 0x3F));
ret[2] = std::uint8_t(0x80 | (ch & 0x3F));
return 3;
}
if (ch <= MaxCodepoint) {
ret[0] = 0xF0 | (ch >> 18);
ret[1] = 0x80 | ((ch >> 12) | 0x3F);
ret[2] = 0x80 | ((ch >> 6) | 0x3F);
ret[3] = 0x80 | (ch | 0x3F);
ret[0] = std::uint8_t(0xF0 | (ch >> 18));
ret[1] = std::uint8_t(0x80 | ((ch >> 12) | 0x3F));
ret[2] = std::uint8_t(0x80 | ((ch >> 6) | 0x3F));
ret[3] = std::uint8_t(0x80 | (ch | 0x3F));
return 4;
}
return 0;
@ -176,7 +176,7 @@ bool isxdigit(char32_t c) noexcept {
inline int codepoint_cmp1(void const *a, void const *b) noexcept {
char32_t c1 = *static_cast<char32_t const *>(a);
char32_t c2 = *static_cast<char32_t const *>(b);
return (c1 - c2);
return (int(c1) - int(c2));
}
inline int codepoint_cmp2(void const *a, void const *b) noexcept {
@ -185,7 +185,7 @@ inline int codepoint_cmp2(void const *a, void const *b) noexcept {
if ((c >= p[0]) && (c <= p[1])) {
return 0;
}
return (c - p[0]);
return (int(c) - int(p[0]));
}
template<
@ -345,7 +345,12 @@ int case_compare(string_range s1, string_range s2) noexcept {
s1 = s1.slice(0, ms);
s2 = s2.slice(0, ms);
for (;;) {
char32_t ldec = s1.front(), rdec = s2.front();
/* enforce correct semantics with signed chars; first convert to
* 8-bit unsigned and then to char32_t (which is always unsigned)
* in order to not get large values from 32-bit unsigned underflow
*/
auto ldec = char32_t(std::uint8_t(s1.front()));
auto rdec = char32_t(std::uint8_t(s2.front()));
if ((ldec <= 0x7F) || !utf::decode(s1, ldec)) {
s1.pop_front();
}
@ -356,8 +361,13 @@ int case_compare(string_range s1, string_range s2) noexcept {
if (d) {
return d;
}
if (s1.empty() || s2.empty()) {
s1l = s1.size();
s2l = s2.size();
break;
}
}
return (s1l < s2l) ? -1 : ((s1 > s2) ? 1 : 0);
return (s1l < s2l) ? -1 : ((s1l > s2l) ? 1 : 0);
}
int case_compare(u32string_range s1, u32string_range s2) noexcept {