Skip to content

Commit

Permalink
Avoid calling member copy function during condition construction
Browse files Browse the repository at this point in the history
  • Loading branch information
MacroModel committed Jul 9, 2023
1 parent 8cd12c1 commit 0f78e5e
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 129 deletions.
12 changes: 11 additions & 1 deletion include/fast_io_core_impl/alias.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ struct cannot_output_type
inline explicit constexpr cannot_output_type() noexcept = default;
};

template <typename T>
concept alias_return_lvalue_ref = !(::std::is_function_v<::std::remove_cvref_t<T>> || alias_printable<::std::remove_cvref_t<T>>) &&
std::is_lvalue_reference_v<T>;

}

template<typename T>
Expand All @@ -37,7 +41,13 @@ inline constexpr auto io_print_forward(T&& t) noexcept
}
else if constexpr(status_io_print_forwardable<char_type,T>)
return status_io_print_forward(io_alias_type<char_type>,::std::forward<T>(t));
else if constexpr(std::is_trivially_copyable_v<no_cvref_t>&&sizeof(no_cvref_t)<=sizeof(std::size_t)*2)
else if constexpr (std::is_trivially_copyable_v<no_cvref_t> &&
#if defined(_MSC_VER) || (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)
sizeof(no_cvref_t) <= 8u
#else
sizeof(no_cvref_t) <= sizeof(std::uintptr_t) * 2
#endif
)
return static_cast<no_cvref_t>(t);
else
return parameter<std::remove_reference_t<T> const&>{t};
Expand Down
275 changes: 147 additions & 128 deletions include/fast_io_freestanding_impl/cond.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
#pragma once

namespace fast_io
{
namespace fast_io {
namespace details {
template <typename T1>
concept cond_value_transferable_value =
::std::is_trivially_copyable_v<T1> &&
#if defined(_MSC_VER) || (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)
sizeof(T1) <= 8u
#else
sizeof(T1) <= (sizeof(std::uintptr_t) * 2)
#endif
;
}

namespace manipulators
{
namespace manipulators {

template<typename T1,typename T2>
struct condition
{
template <typename T1, typename T2>
struct condition {
using manip_tag = manip_tag_t;
using alias_type1 = T1;
using alias_type2 = T2;
Expand All @@ -17,159 +25,170 @@ struct condition
bool pred;
};

template<typename T1,typename T2>
inline constexpr auto cond(bool pred,T1&& t1,T2&& t2) noexcept
{
using t1aliastype=::std::remove_cvref_t<decltype(fast_io::io_print_alias(t1))>;
using t2aliastype=::std::remove_cvref_t<decltype(fast_io::io_print_alias(t2))>;
constexpr bool type_match{::std::same_as<t1aliastype,t2aliastype>};
if constexpr(type_match)
{
if(pred)
{
return fast_io::io_print_alias(t1);
template <typename T1, typename T2>
inline constexpr auto cond(bool pred, T1&& t1, T2&& t2) noexcept {
using t1aliastype = ::std::conditional_t<::fast_io::details::alias_return_lvalue_ref<T1>,
::std::conditional_t<::fast_io::details::cond_value_transferable_value<T1>, ::std::remove_cvref_t<T1>, T1>,
::std::remove_cvref_t<decltype(fast_io::io_print_alias(::std::forward<T1>(t1)))>>;
using t2aliastype = ::std::conditional_t<::fast_io::details::alias_return_lvalue_ref<T2>,
::std::conditional_t<::fast_io::details::cond_value_transferable_value<T2>, ::std::remove_cvref_t<T2>, T2>,
::std::remove_cvref_t<decltype(fast_io::io_print_alias(::std::forward<T2>(t2)))>>;
constexpr bool type_match{::std::same_as<t1aliastype, t2aliastype>};
if constexpr (type_match) {
if (pred) {
return ::fast_io::io_print_alias(::std::forward<T1>(t1));
} else {
return ::fast_io::io_print_alias(::std::forward<T2>(t2));
}
else
{
return fast_io::io_print_alias(t2);
}
}
else
{
if constexpr(sizeof(t1aliastype)<sizeof(t2aliastype))
{
return condition<t2aliastype,t1aliastype>{::fast_io::io_print_alias(t2),::fast_io::io_print_alias(t1),!pred};
}
else
{
return condition<t1aliastype,t2aliastype>{::fast_io::io_print_alias(t1),::fast_io::io_print_alias(t2),pred};
} else {
if constexpr (sizeof(t1aliastype) < sizeof(t2aliastype)) {
return condition<t2aliastype, t1aliastype>{::fast_io::io_print_alias(::std::forward<T2>(t2)), ::fast_io::io_print_alias(::std::forward<T1>(t1)), !pred};
} else {
return condition<t1aliastype, t2aliastype>{::fast_io::io_print_alias(::std::forward<T1>(t1)), ::fast_io::io_print_alias(::std::forward<T2>(t2)), pred};
}
}
}

}
} // namespace manipulators

template<std::integral char_type,typename T1,typename T2>
requires (reserve_printable<char_type,T1>&&reserve_printable<char_type,T2>)
inline constexpr ::std::size_t print_reserve_size(io_reserve_type_t<char_type,::fast_io::manipulators::condition<T1,T2>>) noexcept
{
constexpr std::size_t s1{print_reserve_size(io_reserve_type<char_type,T1>)};
constexpr std::size_t s2{print_reserve_size(io_reserve_type<char_type,T2>)};
if constexpr(s1<s2)
{
template <std::integral char_type, typename T1, typename T2>
requires(reserve_printable<char_type, T1> && reserve_printable<char_type, T2>)
inline constexpr ::std::size_t print_reserve_size(io_reserve_type_t<char_type, ::fast_io::manipulators::condition<T1, T2>>) noexcept {
constexpr std::size_t s1{print_reserve_size(io_reserve_type<char_type, T1>)};
constexpr std::size_t s2{print_reserve_size(io_reserve_type<char_type, T2>)};
if constexpr (s1 < s2) {
return s2;
}
else
{
} else {
return s1;
}
}

template<std::integral char_type,typename T1,typename T2>
requires (scatter_printable<char_type,T1>&&scatter_printable<char_type,T2>)
inline constexpr basic_io_scatter_t<char_type> print_scatter_define(io_reserve_type_t<char_type,::fast_io::manipulators::condition<T1,T2>>,::fast_io::manipulators::condition<T1,T2> c)
{
if(c.pred)
{
return {print_scatter_define(io_reserve_type<char_type,T1>,c.t1)};
}
else
{
return {print_scatter_define(io_reserve_type<char_type,T2>,c.t2)};
template <std::integral char_type, typename T1, typename T2>
requires(scatter_printable<char_type, T1> && scatter_printable<char_type, T2>)
inline constexpr basic_io_scatter_t<char_type> print_scatter_define(io_reserve_type_t<char_type, ::fast_io::manipulators::condition<T1, T2>>, ::fast_io::manipulators::condition<T1, T2> c) {
if (c.pred) {
return {print_scatter_define(io_reserve_type<char_type, T1>, c.t1)};
} else {
return {print_scatter_define(io_reserve_type<char_type, T2>, c.t2)};
}
}

namespace details
{

template<typename char_type,typename T1>
concept cond_ok_dynamic_rsv_printable_impl=
reserve_printable<char_type,T1>||dynamic_reserve_printable<char_type,T1>||scatter_printable<char_type,T1>;

template<typename char_type,typename T1>
concept cond_ok_printable_impl=
cond_ok_dynamic_rsv_printable_impl<char_type,T1>||printable<char_type,T1>;

template<std::integral char_type,typename T1>
inline constexpr ::std::size_t cond_print_reserve_size_impl(T1 t1)
{
if constexpr(scatter_printable<char_type,T1>)
{
return print_scatter_define(io_reserve_type<char_type,T1>,t1).len;
}
else if constexpr(reserve_printable<char_type,T1>)
{
constexpr std::size_t sz{print_reserve_size(io_reserve_type<char_type,T1>)};
namespace details {

template <typename T1, typename T2>
concept cond_transferable_value =
::std::is_trivially_copyable_v<::fast_io::manipulators::condition<T1, T2>> &&
#if defined(_MSC_VER) || (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)
sizeof(::fast_io::manipulators::condition<T1, T2>) <= 8u
#else
sizeof(::fast_io::manipulators::condition<T1, T2>) <= (sizeof(std::uintptr_t) * 2)
#endif
;

template <typename char_type, typename T1>
concept cond_ok_dynamic_rsv_printable_impl =
reserve_printable<char_type, T1> || dynamic_reserve_printable<char_type, T1> || scatter_printable<char_type, T1>;

template <typename char_type, typename T1>
concept cond_ok_printable_impl =
cond_ok_dynamic_rsv_printable_impl<char_type, T1> || printable<char_type, T1>;

template <std::integral char_type, typename T1>
inline constexpr ::std::size_t cond_print_reserve_size_impl(T1&& t1) {
if constexpr (scatter_printable<char_type, T1>) {
return print_scatter_define(io_reserve_type<char_type, T1>, ::std::forward<T1>(t1)).len;
} else if constexpr (reserve_printable<char_type, T1>) {
constexpr std::size_t sz{print_reserve_size(io_reserve_type<char_type, T1>)};
return sz;
}
else
{
return print_reserve_size(io_reserve_type<char_type,T1>,t1);
} else {
return print_reserve_size(io_reserve_type<char_type, T1>, ::std::forward<T1>(t1));
}
}

template<std::integral char_type,typename T1>
inline constexpr char_type* cond_print_reserve_define_impl(char_type* iter,T1 t1)
{
if constexpr(scatter_printable<char_type,T1>)
{
return copy_scatter(print_scatter_define(io_reserve_type<char_type,T1>,t1),iter);
}
else
{
return print_reserve_define(io_reserve_type<char_type,T1>,iter,t1);
template <std::integral char_type, typename T1>
inline constexpr char_type* cond_print_reserve_define_impl(char_type* iter, T1&& t1) {
if constexpr (scatter_printable<char_type, T1>) {
return copy_scatter(print_scatter_define(io_reserve_type<char_type, T1>, ::std::forward<T1>(t1)), iter);
} else {
return print_reserve_define(io_reserve_type<char_type, T1>, iter, ::std::forward<T1>(t1));
}
}

}
} // namespace details

template<std::integral char_type,typename T1,typename T2>
requires ((details::cond_ok_dynamic_rsv_printable_impl<char_type,T1>&&
details::cond_ok_dynamic_rsv_printable_impl<char_type,T1>)
&&(!(scatter_printable<char_type,T1>&&scatter_printable<char_type,T2>)))
inline constexpr ::std::size_t print_reserve_size(io_reserve_type_t<char_type,::fast_io::manipulators::condition<T1,T2>>,::fast_io::manipulators::condition<T1,T2> c)
{
if(c.pred)
{
return ::fast_io::details::cond_print_reserve_size_impl<char_type,T1>(c.t1);
}
else
{
return ::fast_io::details::cond_print_reserve_size_impl<char_type,T2>(c.t2);
template <std::integral char_type, typename T1, typename T2>
requires((details::cond_ok_dynamic_rsv_printable_impl<char_type, T1> &&
details::cond_ok_dynamic_rsv_printable_impl<char_type, T1>) &&
(!(scatter_printable<char_type, T1> && scatter_printable<char_type, T2>))&&
details::cond_transferable_value<T1, T2>)
inline constexpr ::std::size_t print_reserve_size(io_reserve_type_t<char_type, ::fast_io::manipulators::condition<T1, T2>>, ::fast_io::manipulators::condition<T1, T2> c) {
if (c.pred) {
return ::fast_io::details::cond_print_reserve_size_impl<char_type, T1>(c.t1);
} else {
return ::fast_io::details::cond_print_reserve_size_impl<char_type, T2>(c.t2);
}
}

template<std::integral char_type,typename T1,typename T2>
requires ((details::cond_ok_dynamic_rsv_printable_impl<char_type,T1>&&
details::cond_ok_dynamic_rsv_printable_impl<char_type,T2>)
&&(!(scatter_printable<char_type,T1>&&scatter_printable<char_type,T2>)))
inline constexpr char_type* print_reserve_define(io_reserve_type_t<char_type,::fast_io::manipulators::condition<T1,T2>>,char_type* iter,::fast_io::manipulators::condition<T1,T2> c)
{
if(c.pred)
{
return ::fast_io::details::cond_print_reserve_define_impl<char_type,T1>(iter,c.t1);
template <std::integral char_type, typename T1, typename T2>
requires((details::cond_ok_dynamic_rsv_printable_impl<char_type, T1> &&
details::cond_ok_dynamic_rsv_printable_impl<char_type, T1>) &&
(!(scatter_printable<char_type, T1> && scatter_printable<char_type, T2>)) &&
!details::cond_transferable_value<T1, T2>)
inline constexpr ::std::size_t print_reserve_size(io_reserve_type_t<char_type, ::fast_io::manipulators::condition<T1, T2>>, ::fast_io::manipulators::condition<T1, T2> const& c) {
if (c.pred) {
return ::fast_io::details::cond_print_reserve_size_impl<char_type, T1>(c.t1);
} else {
return ::fast_io::details::cond_print_reserve_size_impl<char_type, T2>(c.t2);
}
else
{
return ::fast_io::details::cond_print_reserve_define_impl<char_type,T2>(iter,c.t2);
}

template <std::integral char_type, typename T1, typename T2>
requires((details::cond_ok_dynamic_rsv_printable_impl<char_type, T1> &&
details::cond_ok_dynamic_rsv_printable_impl<char_type, T2>) &&
(!(scatter_printable<char_type, T1> && scatter_printable<char_type, T2>)) &&
details::cond_transferable_value<T1, T2>)
inline constexpr char_type* print_reserve_define(io_reserve_type_t<char_type, ::fast_io::manipulators::condition<T1, T2>>, char_type* iter, ::fast_io::manipulators::condition<T1, T2> c) {
if (c.pred) {
return ::fast_io::details::cond_print_reserve_define_impl<char_type, T1>(iter, c.t1);
} else {
return ::fast_io::details::cond_print_reserve_define_impl<char_type, T2>(iter, c.t2);
}
}

template<::std::integral char_type,typename T1,typename T2,typename bop>
requires ((details::cond_ok_printable_impl<char_type,T1>&&details::cond_ok_printable_impl<char_type,T2>)
&&(!(details::cond_ok_dynamic_rsv_printable_impl<char_type,T1>&&
details::cond_ok_dynamic_rsv_printable_impl<char_type,T2>)))
inline constexpr void print_define(io_reserve_type_t<char_type,::fast_io::manipulators::condition<T1,T2>>,bop b,::fast_io::manipulators::condition<T1,T2> c)
{
if(c.pred)
{
::fast_io::operations::print_freestanding<false>(b,c.t1);
template <std::integral char_type, typename T1, typename T2>
requires((details::cond_ok_dynamic_rsv_printable_impl<char_type, T1> &&
details::cond_ok_dynamic_rsv_printable_impl<char_type, T2>) &&
(!(scatter_printable<char_type, T1> && scatter_printable<char_type, T2>)) &&
!details::cond_transferable_value<T1, T2>)
inline constexpr char_type* print_reserve_define(io_reserve_type_t<char_type, ::fast_io::manipulators::condition<T1, T2>>, char_type* iter, ::fast_io::manipulators::condition<T1, T2> const& c) {
if (c.pred) {
return ::fast_io::details::cond_print_reserve_define_impl<char_type, T1>(iter, c.t1);
} else {
return ::fast_io::details::cond_print_reserve_define_impl<char_type, T2>(iter, c.t2);
}
else
{
::fast_io::operations::print_freestanding<false>(b,c.t2);
}

template <::std::integral char_type, typename T1, typename T2, typename bop>
requires((details::cond_ok_printable_impl<char_type, T1> && details::cond_ok_printable_impl<char_type, T2>) && (!(details::cond_ok_dynamic_rsv_printable_impl<char_type, T1> &&
details::cond_ok_dynamic_rsv_printable_impl<char_type, T2>)) &&
details::cond_transferable_value<T1, T2>)
inline constexpr void print_define(io_reserve_type_t<char_type, ::fast_io::manipulators::condition<T1, T2>>, bop b, ::fast_io::manipulators::condition<T1, T2> c) {
if (c.pred) {
::fast_io::operations::print_freestanding<false>(b, c.t1);
} else {
::fast_io::operations::print_freestanding<false>(b, c.t2);
}
}

template <::std::integral char_type, typename T1, typename T2, typename bop>
requires((details::cond_ok_printable_impl<char_type, T1> && details::cond_ok_printable_impl<char_type, T2>) && (!(details::cond_ok_dynamic_rsv_printable_impl<char_type, T1> && details::cond_ok_dynamic_rsv_printable_impl<char_type, T2>)) &&
!details::cond_transferable_value<T1, T2>)
inline constexpr void print_define(io_reserve_type_t<char_type, ::fast_io::manipulators::condition<T1, T2>>, bop b, ::fast_io::manipulators::condition<T1, T2> const& c) {
if (c.pred) {
::fast_io::operations::print_freestanding<false>(b, c.t1);
} else {
::fast_io::operations::print_freestanding<false>(b, c.t2);
}
}

} // namespace fast_io

0 comments on commit 0f78e5e

Please sign in to comment.