Skip to content

Commit

Permalink
Export internal changes
Browse files Browse the repository at this point in the history
  • Loading branch information
foonathan committed May 5, 2023
1 parent b5378b5 commit 1848ee3
Show file tree
Hide file tree
Showing 171 changed files with 4,025 additions and 3,465 deletions.
2 changes: 1 addition & 1 deletion tc/algorithm/accumulate.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

// think-cell public library
//
// Copyright (C) 2016-2022 think-cell Software GmbH
// Copyright (C) 2016-2023 think-cell Software GmbH
//
// 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
Expand Down
2 changes: 1 addition & 1 deletion tc/algorithm/accumulator.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

// think-cell public library
//
// Copyright (C) 2016-2022 think-cell Software GmbH
// Copyright (C) 2016-2023 think-cell Software GmbH
//
// 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
Expand Down
137 changes: 71 additions & 66 deletions tc/algorithm/algorithm.h

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions tc/algorithm/algorithm.t.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

// think-cell public library
//
// Copyright (C) 2016-2022 think-cell Software GmbH
// Copyright (C) 2016-2023 think-cell Software GmbH
//
// 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
Expand Down Expand Up @@ -363,11 +363,11 @@ UNITTESTDEF(constexpr_sort_test) {

auto Test = [](auto rngn) noexcept {
auto vecn = tc::explicit_cast<tc::vector<int>>(rngn);
_ASSERTEQUAL(modified(vecn, tc::sort_inplace(_)), modified(vecn, tc::constexpr_sort_inplace_detail::constexpr_sort_inplace(tc::begin(_), tc::end(_), tc::fn_less())));
_ASSERTEQUAL(tc_modified(vecn, tc::sort_inplace(_)), tc_modified(vecn, tc::constexpr_sort_inplace_detail::constexpr_sort_inplace(tc::begin(_), tc::end(_), tc::fn_less())));
};

for( int i = 0; i < 17; ++i ) {
Test(tc::begin_next<tc::return_take>([&](auto sink) noexcept { for(;;) RETURN_IF_BREAK( tc::continue_if_not_break(sink, dist(gen)) ); }, dist(gen)));
Test(tc::begin_next<tc::return_take>([&](auto sink) noexcept { for(;;) tc_yield(sink, dist(gen)); }, dist(gen)));
Test(tc::iota(0, i));
Test(tc::reverse(tc::iota(0, i)));
Test(tc::repeat_n(i, 0));
Expand Down
2 changes: 1 addition & 1 deletion tc/algorithm/any_accu.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

// think-cell public library
//
// Copyright (C) 2016-2022 think-cell Software GmbH
// Copyright (C) 2016-2023 think-cell Software GmbH
//
// 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
Expand Down
50 changes: 26 additions & 24 deletions tc/algorithm/append.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

// think-cell public library
//
// Copyright (C) 2016-2022 think-cell Software GmbH
// Copyright (C) 2016-2023 think-cell Software GmbH
//
// 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
Expand All @@ -26,28 +26,28 @@ namespace tc {
namespace append_detail {
template<typename Rng, typename TTarget>
concept conv_enc_needed =
tc::is_char<TTarget>::value &&
tc::is_range_with_iterators<Rng>::value &&
tc::is_char<tc::range_value_t<Rng>>::value &&
tc::char_type<TTarget> &&
tc::range_with_iterators<Rng> &&
tc::char_type<tc::range_value_t<Rng>> &&
!std::is_same<TTarget, tc::range_value_t<Rng>>::value;

// in general, do not use Cont::insert() or Cont(it, it)
// iterators are slower than for_each in many cases (eg. filter ranges)
template<typename Rng, typename Cont>
concept range_insertable =
(!conv_enc_needed<Rng, tc::range_value_t<Cont>>) &&
has_mem_fn_reserve<Cont>::value &&
has_mem_fn_reserve<Cont> &&
!tc::is_concat_range<std::remove_cvref_t<Rng>>::value && // it might be more efficient to append by ranges than by iterators
tc::common_range<Rng> &&
std::is_convertible<
typename std::iterator_traits<std::remove_reference_t<decltype(tc::begin(std::declval<Rng>()))>>::iterator_category,
std::convertible_to<
typename std::iterator_traits<tc::iterator_t<Rng>>::iterator_category,
std::random_access_iterator_tag
>::value &&
tc::econstructionIMPLICIT==tc::construction_restrictiveness<tc::range_value_t<Cont>, tc::iter_reference_t<tc::iterator_t<Rng>>>::value;
> &&
tc::econstructionIMPLICIT==tc::construction_restrictiveness<tc::range_value_t<Cont>, std::iter_reference_t<tc::iterator_t<Rng>>>::value;
}

namespace append_no_adl {
template< typename Cont, bool bReserve = has_mem_fn_reserve<Cont>::value>
template< typename Cont, bool bReserve = has_mem_fn_reserve<Cont>>
struct [[nodiscard]] appender_type;

template< typename Cont>
Expand All @@ -59,7 +59,9 @@ namespace tc {

template<typename T>
constexpr void operator()(T&& t) const& noexcept(noexcept(tc::cont_emplace_back(m_cont, std::forward<T>(t))))
requires requires { tc::cont_emplace_back(std::declval<Cont&>(), std::forward<T>(t)); }
requires
(!tc::char_like<tc::range_value_t<Cont>> || tc::safely_convertible_to<T&&, tc::range_value_t<Cont>>) &&
requires { tc::cont_emplace_back(std::declval<Cont&>(), std::forward<T>(t)); }
{
tc::cont_emplace_back(m_cont, std::forward<T>(t)); // MAYTHROW
}
Expand All @@ -72,7 +74,7 @@ namespace tc {
}

void chunk(append_detail::conv_enc_needed<tc::range_value_t<Cont>> auto&& rng) const& return_MAYTHROW(
tc::implicit_cast<void>(tc::for_each(tc::must_convert_enc<tc::range_value_t<Cont>>(tc_move_if_owned(rng)), *this))
tc::implicit_cast<void>(tc::for_each(tc::convert_enc<tc::range_value_t<Cont>>(tc_move_if_owned(rng)), *this))
)
};

Expand All @@ -86,7 +88,7 @@ namespace tc {
// https://stackoverflow.com/questions/51933397/sfinae-method-completely-disables-base-classs-template-method-in-clang
template< typename Rng, ENABLE_SFINAE, std::enable_if_t<
!append_detail::conv_enc_needed<Rng, tc::range_value_t<Cont>> &&
tc::has_size<Rng>::value &&
tc::has_size<Rng> &&
!append_detail::range_insertable<Rng, Cont>
>* = nullptr>
constexpr auto chunk(Rng&& rng, int = 0) const& return_decltype_MAYTHROW(
Expand All @@ -109,22 +111,22 @@ namespace tc {
using appender_t = decltype(tc::appender(std::declval<Cont>()));

template<typename Rng, typename Cont>
concept appendable = tc::has_for_each<Rng, tc::appender_t<Cont>>::value;
concept appendable = tc::has_for_each<Rng, tc::appender_t<Cont>>;

// Disallow 0 == sizeof...(Rngs), so that overload taking single argument tc::tuple<Cont, Rng...> is rejected
// Disallow 0 == sizeof...(Rng), so that overload taking single argument tc::tuple<Cont, Rng...> is rejected
template< typename RangeReturn = tc::return_void, typename Cont, tc::appendable<Cont&> Rng>
constexpr decltype(auto) append(Cont&& cont, Rng&& rng) MAYTHROW {
static_assert( !std::is_const<Cont>::value, "Cannot append to const container" );
static_assert( !tc::is_range_with_iterators<Cont>::value || std::is_lvalue_reference<Cont>::value, "Append to rvalue intentional?" );
static_assert( !tc::range_with_iterators<Cont> || std::is_lvalue_reference<Cont>::value, "Append to rvalue intentional?" );

if constexpr( !tc::is_range_with_iterators<Cont>::value || (
if constexpr( !tc::range_with_iterators<Cont> || (
std::is_same<RangeReturn, tc::return_void>::value &&
noexcept(tc::for_each(std::forward<Rng>(rng), tc::appender(cont)))
) ) {
static_assert( std::is_same<RangeReturn, tc::return_void>::value, "RangeReturn not supported, if appending to stream." );

tc::for_each(std::forward<Rng>(rng), tc::appender(cont));
} else if constexpr( tc::is_random_access_range<Cont>::value || has_mem_fn_reserve<Cont>::value ) {
} else if constexpr( tc::random_access_range<Cont> || has_mem_fn_reserve<Cont> ) {
auto const nOffset = tc::size_raw(cont);
try {
tc::for_each(std::forward<Rng>(rng), tc::appender(cont));
Expand All @@ -142,7 +144,7 @@ namespace tc {
// assume iterators are stable to get iterator to first inserted element
auto const it = tc::back<tc::return_element_or_null>(cont);
auto FirstAppendedElement = [&]() noexcept {
return it ? modified(it, ++_) : tc::begin(cont);
return it ? tc_modified(it, ++_) : tc::begin(cont);
};
try {
tc::for_each(std::forward<Rng>(rng), tc::appender(cont)); // MAYTHROW
Expand All @@ -156,15 +158,15 @@ namespace tc {
}
}

template< typename RangeReturn = tc::return_void, typename Cont, tc::appendable<Cont&>... Rngs> requires (1 < sizeof...(Rngs))
constexpr decltype(auto) append(Cont&& cont, Rngs&&... rngs) MAYTHROW {
return tc::append<RangeReturn>(std::forward<Cont>(cont), tc::concat(std::forward<Rngs>(rngs)...));
template< typename RangeReturn = tc::return_void, typename Cont, tc::appendable<Cont&>... Rng> requires (1 < sizeof...(Rng))
constexpr decltype(auto) append(Cont&& cont, Rng&&... rng) MAYTHROW {
return tc::append<RangeReturn>(std::forward<Cont>(cont), tc::concat(std::forward<Rng>(rng)...));
}

namespace explicit_convert_to_container_detail {
template<typename TTarget, typename Rng0, typename... RngN>
using use_ctor=tc::constant<
tc::is_base_of<TTarget, std::remove_cvref_t<Rng0> >::value &&
tc::derived_from<std::remove_cvref_t<Rng0>, TTarget> &&
(
0==sizeof...(RngN) ||
(!std::is_reference<Rng0>::value && !std::is_const<Rng0>::value)
Expand All @@ -174,7 +176,7 @@ namespace tc {

namespace explicit_convert_adl {
template<typename Cont>
concept appendable_container = has_mem_fn_push_back<Cont>::value || has_emplace_back<Cont, tc::range_value_t<Cont>>::value;
concept appendable_container = has_mem_fn_push_back<Cont> || has_emplace_back<Cont, tc::range_value_t<Cont>>::value;

template<appendable_container TTarget, typename Rng0, tc::appendable<TTarget&>... RngN>
requires explicit_convert_to_container_detail::use_ctor<TTarget, Rng0, RngN...>::value
Expand Down
24 changes: 23 additions & 1 deletion tc/algorithm/append.t.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

// think-cell public library
//
// Copyright (C) 2016-2022 think-cell Software GmbH
// Copyright (C) 2016-2023 think-cell Software GmbH
//
// 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
Expand Down Expand Up @@ -84,4 +84,26 @@ UNITTESTDEF(SReportStreamTest) {
tc::append(rs, tc::debug_output(STestError3()));
_ASSERTEQUAL(rs.m_str, "abc[10][nullptr]STestError3(STestError2(5, STestError1(-1)), nullptr)");
}


UNITTESTDEF(SReportStreamExceptionTest) {
tc::SReportStream rs;
tc::append(rs,
"Generate msg#0: ", [](auto sink) MAYTHROW {
tc::for_each("<part0>", sink);
tc::for_each([](auto sink) MAYTHROW { throw 0; }, sink);
throw 1;
}, "\n"
"Generate msg#1: ", [](tc::report_appender appdr) MAYTHROW {
tc::for_each([](auto sink) MAYTHROW { throw 0; }, appdr);
tc::for_each([](auto sink) MAYTHROW { throw 1; }, appdr);
tc::for_each("<part2>", appdr);
throw 0;
}, "\n"
);
_ASSERTEQUAL(rs.m_str,
"Generate msg#0: <part0><tc::report threw exception>\n"
"Generate msg#1: <tc::report threw exception><tc::report threw exception><part2><tc::report threw exception>\n"
);
}
#endif
6 changes: 3 additions & 3 deletions tc/algorithm/best_element.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

// think-cell public library
//
// Copyright (C) 2016-2022 think-cell Software GmbH
// Copyright (C) 2016-2023 think-cell Software GmbH
//
// 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
Expand All @@ -18,7 +18,7 @@
namespace tc {

template< typename RangeReturn, typename Better, typename Rng>
[[nodiscard]] decltype(auto) best_element_impl(Better better, Rng&& rng) MAYTHROW {
[[nodiscard]] constexpr decltype(auto) best_element_impl(Better better, Rng&& rng) MAYTHROW {
if constexpr( RangeReturn::requires_iterator ) {
auto const itEnd=tc::end(rng); // MAYTHROW
decltype(tc::begin(rng)) ait[2]={ tc::begin(rng) }; // MAYTHROW
Expand All @@ -30,7 +30,7 @@ namespace tc {
for(;;){
for( int i=0; i!=2; ++i ) { // we expect the compiler to unroll this loop
// aoref[i] is constructed, aoref[1-i] is not constructed
scope_exit( aoref[i].dtor() ); // also required in case of exception
tc_scope_exit { aoref[i].dtor(); }; // also required in case of exception
ait[1-i]=ait[i];
for(;;) {
// aoref[i] is constructed, aoref[1-i] is not constructed
Expand Down
24 changes: 12 additions & 12 deletions tc/algorithm/binary_operators.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

// think-cell public library
//
// Copyright (C) 2016-2022 think-cell Software GmbH
// Copyright (C) 2016-2023 think-cell Software GmbH
//
// 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
Expand Down Expand Up @@ -29,7 +29,7 @@ namespace tc {
} else { \
static_assert( \
std::is_same<Result, tc::decay_t<Lhs>>::value \
|| !is_compound_available<tc::decay_t<Lhs>, Rhs&&>::value, \
|| !is_compound_available<tc::decay_t<Lhs>, Rhs&&>, \
"conversion_t provides a conversion, despite " #op "= being offered by the original type" \
); \
return _; \
Expand Down Expand Up @@ -57,15 +57,15 @@ namespace tc {
struct TC_EMPTY_BASES name : std::conditional_t<std::is_void<Base>::value, tc::empty_chain<name<void>>, Base> { \
private: \
template< typename Lhs, typename Rhs > \
using is_compound_available = tc::generic_operator_helper::has_mem_fn_compound_ ##name<Lhs&, Rhs>; \
static constexpr bool is_compound_available = tc::generic_operator_helper::has_mem_fn_compound_ ##name<Lhs&, Rhs>; \
template< typename Lhs, typename Rhs > \
using conversion_t = typename binary_operator_conversions::internal_##name##_conversion_type<tc::decay_t<Lhs>, tc::decay_t<Rhs>>::type; \
/*If we're not forwarding an rvalue, we're calling the operator on the result of tc::decay_copy(Lhs&), which is tc::decay_t<Lhs>& \
If we're forwarding an rvalue, we're calling the operator on remove_reference_t<Lhs>&. But is_same<tc::decay_t<Lhs>, remove_reference_t<Lhs>>::value. */ \
template< typename Lhs, typename Rhs > \
using is_operation_available = tc::constant< \
tc::is_base_of<name, conversion_t<Lhs, Rhs>>::value \
&& is_compound_available<conversion_t<Lhs, Rhs>, Rhs>::value \
tc::derived_from<conversion_t<Lhs, Rhs>, name> \
&& is_compound_available<conversion_t<Lhs, Rhs>, Rhs> \
>; \
public: \
GENERIC_OP_BODY( op, _.operator op##=(std::forward<Rhs>(rhs)) ); \
Expand All @@ -75,21 +75,21 @@ namespace tc {
struct TC_EMPTY_BASES external_ ##name : std::conditional_t<std::is_void<Base>::value, tc::empty_chain<external_ ##name <void>>, Base> { \
private: \
template< typename Lhs, typename Rhs > \
using is_compound_available = tc::generic_operator_helper::has_compound_ ##name<Lhs&, Rhs>; \
static constexpr bool is_compound_available = tc::generic_operator_helper::has_compound_ ##name<Lhs&, Rhs>; \
template< typename Lhs, typename Rhs > \
using conversion_t = tc::decay_t<Lhs>; \
static_assert( std::is_fundamental<Other>::value, "external_" #name " is only meant for fundamental types" ); \
STATICASSERTSAME( tc::decay_t<Other>, Other ); \
template< typename Lhs, typename Rhs > \
using is_operation_available = tc::constant< \
tc::is_base_of<Other, std::remove_reference_t<Lhs>>::value \
&& tc::is_base_of<external_ ##name<Other, Base>, std::remove_reference_t<Rhs>>::value \
tc::derived_from<std::remove_reference_t<Lhs>, Other> \
&& tc::derived_from<std::remove_reference_t<Rhs>, external_ ##name<Other, Base>> \
/* Same reasoning as in the internal operator */ \
&& is_compound_available<tc::decay_t<Lhs>, Rhs>::value \
&& is_compound_available<tc::decay_t<Lhs>, Rhs> \
>; \
public: \
GENERIC_OP_BODY( op, { \
static_assert(!tc::generic_operator_helper::has_mem_fn_compound_ ##name<decltype((_)), decltype(std::forward<Rhs>(rhs))>::value); \
static_assert(!tc::generic_operator_helper::has_mem_fn_compound_ ##name<decltype((_)), decltype(std::forward<Rhs>(rhs))>); \
_ op##= std::forward<Rhs>(rhs); \
} ); \
}; \
Expand Down Expand Up @@ -208,7 +208,7 @@ namespace tc {
namespace no_adl { \
template<typename Base = void, std::size_t nTransformDepth = 0, typename PrePostOperation = prepostopdefault> \
struct TC_EMPTY_BASES scalar_ ## name : std::conditional_t<std::is_void<Base>::value, tc::empty_chain<scalar_ ## name<void, nTransformDepth, PrePostOperation>>, Base> { \
template<typename Lhs, typename Rhs> requires tc::is_base_of_decayed<scalar_ ## name, Lhs>::value && requires { \
template<tc::decayed_derived_from<scalar_ ## name> Lhs, typename Rhs> requires requires { \
std::declval<Lhs>().template transform<nTransformDepth>(std::declval<scalar_binary_op_detail::no_adl::func<fnop, Rhs>>()); \
} \
[[nodiscard]] friend constexpr decltype(auto) operator op(Lhs&& lhs, Rhs const& rhs) noexcept { \
Expand All @@ -218,7 +218,7 @@ namespace tc {
return _; \
} \
\
template<typename Lhs, typename Rhs> requires tc::is_base_of_decayed<scalar_ ## name, Lhs>::value && requires { \
template<tc::decayed_derived_from<scalar_ ## name> Lhs, typename Rhs> requires requires { \
tc::for_each(std::declval<Lhs&>(), std::declval<scalar_binary_op_detail::no_adl::func<fnassignop, Rhs>>()); \
} \
friend constexpr Lhs& operator op ## =(Lhs& lhs, Rhs const& rhs) noexcept { \
Expand Down
Loading

0 comments on commit 1848ee3

Please sign in to comment.