Commit 704c7ec4 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

Decay char-array and trivial args to throw_exception

Summary:
[Folly] Decay char-array and trivial args to `throw_exception` and `terminate_with`.

The motivation is to ensure smaller call-site code size in the common cases, where the solitary argument is a string literal. Extend to cases where arguments are numbers and the like as well, since that is simple enough and is something that `Function` already does.

Reviewed By: aary

Differential Revision: D23550096

fbshipit-source-id: d3a2066dc28dc4cfac6b65e2b8972613ce55d06c
parent ad37aadb
......@@ -23,6 +23,7 @@
#include <folly/CPortability.h>
#include <folly/CppAttributes.h>
#include <folly/Portability.h>
#include <folly/Traits.h>
namespace folly {
......@@ -48,52 +49,75 @@ template <typename Ex>
throw_exception(static_cast<Ex&&>(ex));
}
// clang-format off
namespace detail {
template <typename T>
FOLLY_ERASE T&& to_exception_arg_(T&& t) {
return static_cast<T&&>(t);
}
template <std::size_t N>
FOLLY_ERASE char const* to_exception_arg_(
char const (&array)[N]) {
return static_cast<char const*>(array);
}
struct throw_exception_arg_array_ {
template <typename R>
using v = std::remove_extent_t<std::remove_reference_t<R>>;
template <typename R>
using apply = std::enable_if_t<std::is_same<char const, v<R>>::value, v<R>*>;
};
struct throw_exception_arg_trivial_ {
template <typename R>
using apply = remove_cvref_t<R>;
};
struct throw_exception_arg_base_ {
template <typename R>
using apply = R;
};
template <typename R>
using throw_exception_arg_ = //
conditional_t<
std::is_array<std::remove_reference_t<R>>::value,
throw_exception_arg_array_,
conditional_t<
is_trivially_copyable_v<remove_cvref_t<R>>,
throw_exception_arg_trivial_,
throw_exception_arg_base_>>;
template <typename R>
using throw_exception_arg_t =
typename throw_exception_arg_<R>::template apply<R>;
template <typename Ex, typename... Args>
[[noreturn]] FOLLY_NOINLINE FOLLY_COLD void throw_exception_(Args&&... args) {
throw_exception(Ex(static_cast<Args&&>(args)...));
[[noreturn]] FOLLY_NOINLINE FOLLY_COLD void throw_exception_(Args... args) {
throw_exception(Ex(static_cast<Args>(args)...));
}
template <typename Ex, typename... Args>
[[noreturn]] FOLLY_NOINLINE FOLLY_COLD void terminate_with_(
Args&&... args) noexcept {
throw_exception(Ex(static_cast<Args&&>(args)...));
Args... args) noexcept {
throw_exception(Ex(static_cast<Args>(args)...));
}
} // namespace detail
// clang-format on
/// throw_exception
///
/// Construct and throw an exception if exceptions are enabled, or terminate if
/// compiled with -fno-exceptions.
///
/// Converts any arguments of type `char const[N]` to `char const*`.
/// Does not perfectly forward all its arguments. Instead, in the interest of
/// minimizing common-case inline code size, decays its arguments as follows:
/// * refs to arrays of char const are decayed to char const*
/// * refs to arrays are otherwise invalid
/// * refs to trivial types are decayed to values
///
/// The reason for treating refs to arrays as invalid is to avoid having two
/// behaviors for refs to arrays, one for the general case and one for where the
/// inner type is char const. Having two behaviors can be surprising, so avoid.
template <typename Ex, typename... Args>
[[noreturn]] FOLLY_ERASE void throw_exception(Args&&... args) {
detail::throw_exception_<Ex>(
detail::to_exception_arg_(static_cast<Args&&>(args))...);
detail::throw_exception_<Ex, detail::throw_exception_arg_t<Args&&>...>(
static_cast<Args&&>(args)...);
}
/// terminate_with
///
/// Terminates as if by forwarding to throw_exception but in a noexcept context.
// clang-format off
/// Terminates as if by forwarding to throw_exception within a noexcept context.
template <typename Ex, typename... Args>
[[noreturn]] FOLLY_ERASE void
terminate_with(Args&&... args) noexcept {
detail::terminate_with_<Ex>(
detail::to_exception_arg_(static_cast<Args&&>(args))...);
[[noreturn]] FOLLY_ERASE void terminate_with(Args&&... args) {
detail::terminate_with_<Ex, detail::throw_exception_arg_t<Args>...>(
static_cast<Args&&>(args)...);
}
// clang-format on
/// invoke_cold
///
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment