-
Notifications
You must be signed in to change notification settings - Fork 7
Forwarding reference #21
Copy link
Copy link
Open
Description
Maybe Forwarding reference is needed here
Fix
In file
v4/proxy.hline 298
origin:
template <class P, class F, bool IsDirect, class D, qualifier_type Q, bool NE,
class R, class... Args>
R invoke_dispatch(add_qualifier_t<proxy<F>, Q> self,
Args... args) noexcept(NE) {
/* ... */
}fix:
template <class P, class F, bool IsDirect, class D, qualifier_type Q, bool NE,
class R, class... Args>
R invoke_dispatch(add_qualifier_t<proxy<F>, Q> self,
Args&&... args) noexcept(NE) { /// CHANGE HERE
/* ... */
}Also, v4/proxy.h line 330 should also change from Args... to Args&&...
origin:
struct overload_traits_impl : applicable_traits {
using return_type = R;
template <class F>
using dispatcher_type = R (*)(add_qualifier_t<proxy<F>, Q>,
Args...) noexcept(NE);
template <class P, class F, bool IsDirect, class D>
static constexpr auto dispatcher =
&invoke_dispatch<P, F, IsDirect, D, Q, NE, R, Args...>;
template <class P, bool IsDirect, class D>
static constexpr bool applicable_ptr =
invocable_dispatch<P, IsDirect, D, Q, NE, R, Args...>;
};fix:
struct overload_traits_impl : applicable_traits {
using return_type = R;
template <class F>
using dispatcher_type = R (*)(add_qualifier_t<proxy<F>, Q>,
Args&&...) noexcept(NE); /// CHANGE HERE
template <class P, class F, bool IsDirect, class D>
static constexpr auto dispatcher =
&invoke_dispatch<P, F, IsDirect, D, Q, NE, R, Args...>;
template <class P, bool IsDirect, class D>
static constexpr bool applicable_ptr =
invocable_dispatch<P, IsDirect, D, Q, NE, R, Args...>;
};Perf
Forwarding reference can avoid the need for a second copy of objects with high copy overhead, but it is not friendly to scalar objects and trivial objects. Consider using smart_forward_t instead. In v4/proxy.h line 897, the function pointer call here cannot be inlined, so the parameter passing value at this location needs to be optimized!
Args...double-copy
Args&&...Arguments must be passed via stack, even if they are scalar or trivial.
smart_forward_t<Args>...Best solution
// Is trivial for the purposes of calls. (trivially destruct, copy and move)
// See https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial-parameters .
template <typename T>
struct is_call_trivial : public std::bool_constant<
std::is_trivially_destructible<T>::value
&& std::is_trivially_copy_constructible<T>::value
&& std::is_trivially_move_constructible<T>::value
> {};
// Used to choose either perfect forwarding or pass-by-value.
// Pass-by-value is faster for scalar types because they can
// be passed by the register rather than the stack.
template <typename T>
using smart_forward_t = std::conditional_t<std::is_scalar<T>::value
|| (sizeof(T) <= sizeof(void*) && is_call_trivial<T>::value),
T, T&&>;Also see https://reviews.llvm.org/D55045
// Used to choose between perfect forwarding or pass-by-value. Pass-by-value is
// faster for types that can be passed in registers.
template <typename _Tp>
using __fast_forward =
typename _VSTD::conditional<_VSTD::is_scalar<_Tp>::value, _Tp, _Tp&&>::type;Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels