Allow efficient construction of `absl::Status` from `std::string&&` using the convenience functions. PiperOrigin-RevId: 966927834 Change-Id: Idc323be579b159786a66fedf7b44f9fdcd826f71
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h index 03b0663..81f6ce4 100644 --- a/absl/status/internal/status_internal.h +++ b/absl/status/internal/status_internal.h
@@ -82,6 +82,9 @@ using Payloads = absl::InlinedVector<Payload, 1>; +template <typename T> +using EnableIfString = std::enable_if_t<std::is_same_v<T, std::string>>; + // Reference-counted representation of Status data. class StatusRep { public: @@ -92,16 +95,13 @@ message_(message_arg), payloads_(std::move(payloads_arg)) {} -#ifndef SWIG - template <typename String, - typename = std::enable_if_t<std::is_same_v<String, std::string>>> + template <typename String, typename = EnableIfString<String>> StatusRep(absl::StatusCode code_arg, String&& message_arg, std::unique_ptr<status_internal::Payloads> payloads_arg) : ref_(int32_t{1}), code_(code_arg), message_(std::forward<String>(message_arg)), payloads_(std::move(payloads_arg)) {} -#endif // SWIG absl::StatusCode code() const { return code_; } const std::string& message() const { return message_; }
diff --git a/absl/status/status.cc b/absl/status/status.cc index 155c5d8..555ae42 100644 --- a/absl/status/status.cc +++ b/absl/status/status.cc
@@ -171,7 +171,7 @@ namespace status_internal { // We use an int in the template parameter to shorten mangled names. template <int error_code> -Status MakeErrorImpl(string_view message, SourceLocation loc) { +Status MakeErrorStringViewImpl(string_view message, SourceLocation loc) { return Status(static_cast<StatusCode>(error_code), message, loc); } @@ -179,23 +179,55 @@ // If we add more error code, we need to add their values on this list. // Using ints here instead of static_cast<int>(StatusCode::kFoo) makes it easier // to see that the list is complete. -template Status MakeErrorImpl<0>(string_view, SourceLocation); -template Status MakeErrorImpl<1>(string_view, SourceLocation); -template Status MakeErrorImpl<2>(string_view, SourceLocation); -template Status MakeErrorImpl<3>(string_view, SourceLocation); -template Status MakeErrorImpl<4>(string_view, SourceLocation); -template Status MakeErrorImpl<5>(string_view, SourceLocation); -template Status MakeErrorImpl<6>(string_view, SourceLocation); -template Status MakeErrorImpl<7>(string_view, SourceLocation); -template Status MakeErrorImpl<8>(string_view, SourceLocation); -template Status MakeErrorImpl<9>(string_view, SourceLocation); -template Status MakeErrorImpl<10>(string_view, SourceLocation); -template Status MakeErrorImpl<11>(string_view, SourceLocation); -template Status MakeErrorImpl<12>(string_view, SourceLocation); -template Status MakeErrorImpl<13>(string_view, SourceLocation); -template Status MakeErrorImpl<14>(string_view, SourceLocation); -template Status MakeErrorImpl<15>(string_view, SourceLocation); -template Status MakeErrorImpl<16>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<0>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<1>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<2>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<3>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<4>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<5>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<6>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<7>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<8>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<9>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<10>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<11>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<12>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<13>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<14>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<15>(string_view, SourceLocation); +template Status MakeErrorStringViewImpl<16>(string_view, SourceLocation); + +// Same as above, but for rvalue strings. +#ifndef SWIG +// We use an int in the template parameter to shorten mangled names. +template <int error_code> +Status MakeErrorStringRvalueImpl(std::string&& message, SourceLocation loc) { + return Status(static_cast<StatusCode>(error_code), std::move(message), loc); +} + +// Explicit instantiation for all the error codes. +// If we add more error code, we need to add their values on this list. +// Using ints here instead of static_cast<int>(StatusCode::kFoo) makes it easier +// to see that the list is complete. +template Status MakeErrorStringRvalueImpl<0>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<1>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<2>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<3>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<4>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<5>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<6>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<7>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<8>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<9>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<10>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<11>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<12>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<13>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<14>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<15>(std::string&&, SourceLocation); +template Status MakeErrorStringRvalueImpl<16>(std::string&&, SourceLocation); +#endif // SWIG + } // namespace status_internal bool IsAborted(const Status& status) {
diff --git a/absl/status/status.h b/absl/status/status.h index 3103e79..f86065a 100644 --- a/absl/status/status.h +++ b/absl/status/status.h
@@ -469,8 +469,7 @@ // Same as above but for rvalue string. // Note: using a template to disambiguate the case of matching string_view and // string&& (e.g. char*) as a template lowers the priority of the overload. - template <typename String, - typename = std::enable_if_t<std::is_same_v<String, std::string>>> + template <typename String, typename = status_internal::EnableIfString<String>> Status(absl::StatusCode code, String&& msg, absl::SourceLocation loc = SourceLocation::current()); #endif // SWIG @@ -890,45 +889,176 @@ // These convenience functions create an `absl::Status` object with an error // code as indicated by the associated function name, using the error message // passed in `message`. +// Note: using a template for the rvalue message overload to disambiguate the +// case of matching string_view and string&& (e.g. char*) as a template lowers +// the priority of the overload. + +// AbortedError Status AbortedError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status AbortedError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// AlreadyExistsError Status AlreadyExistsError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status AlreadyExistsError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// CancelledError Status CancelledError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status CancelledError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// DataLossError Status DataLossError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status DataLossError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// DeadlineExceededError Status DeadlineExceededError( absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status DeadlineExceededError( + String&& message, absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// FailedPreconditionError Status FailedPreconditionError( absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status FailedPreconditionError( + String&& message, absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// InternalError Status InternalError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status InternalError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// InvalidArgumentError Status InvalidArgumentError( absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status InvalidArgumentError( + String&& message, absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// NotFoundError Status NotFoundError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status NotFoundError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// OutOfRangeError Status OutOfRangeError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status OutOfRangeError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// PermissionDeniedError Status PermissionDeniedError( absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status PermissionDeniedError( + String&& message, absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// ResourceExhaustedError Status ResourceExhaustedError( absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status ResourceExhaustedError( + String&& message, absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// UnauthenticatedError Status UnauthenticatedError( absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status UnauthenticatedError( + String&& message, absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// UnavailableError Status UnavailableError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status UnavailableError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// UnimplementedError Status UnimplementedError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); + +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status UnimplementedError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + +// UnknownError Status UnknownError(absl::string_view message, absl::SourceLocation loc = SourceLocation::current()); +#ifndef SWIG +template <typename String, typename = status_internal::EnableIfString<String>> +Status UnknownError(String&& message, + absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG + // ErrnoToStatusCode() // // Returns the StatusCode for `error_number`, which should be an `errno` value. @@ -1143,110 +1273,339 @@ namespace status_internal { // We use an int in the template parameter to shorten mangled names. template <int error_code> -Status MakeErrorImpl(string_view message, SourceLocation loc); +Status MakeErrorStringViewImpl(string_view message, SourceLocation loc); // Make the instantiations extern to reduce bloat on callers. #ifndef SWIG -extern template Status MakeErrorImpl<0>(string_view, SourceLocation); -extern template Status MakeErrorImpl<1>(string_view, SourceLocation); -extern template Status MakeErrorImpl<2>(string_view, SourceLocation); -extern template Status MakeErrorImpl<3>(string_view, SourceLocation); -extern template Status MakeErrorImpl<4>(string_view, SourceLocation); -extern template Status MakeErrorImpl<5>(string_view, SourceLocation); -extern template Status MakeErrorImpl<6>(string_view, SourceLocation); -extern template Status MakeErrorImpl<7>(string_view, SourceLocation); -extern template Status MakeErrorImpl<8>(string_view, SourceLocation); -extern template Status MakeErrorImpl<9>(string_view, SourceLocation); -extern template Status MakeErrorImpl<10>(string_view, SourceLocation); -extern template Status MakeErrorImpl<11>(string_view, SourceLocation); -extern template Status MakeErrorImpl<12>(string_view, SourceLocation); -extern template Status MakeErrorImpl<13>(string_view, SourceLocation); -extern template Status MakeErrorImpl<14>(string_view, SourceLocation); -extern template Status MakeErrorImpl<15>(string_view, SourceLocation); -extern template Status MakeErrorImpl<16>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<0>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<1>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<2>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<3>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<4>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<5>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<6>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<7>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<8>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<9>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<10>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<11>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<12>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<13>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<14>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<15>(string_view, SourceLocation); +extern template Status MakeErrorStringViewImpl<16>(string_view, SourceLocation); #endif // SWIG template <StatusCode error_code> -Status MakeError(string_view message, SourceLocation loc) { - Status out = MakeErrorImpl<static_cast<int>(error_code)>(message, loc); +Status MakeErrorFromStringView(string_view message, SourceLocation loc) { + Status out = + MakeErrorStringViewImpl<static_cast<int>(error_code)>(message, loc); // -Wassume warning complains about potential side effects of `ok()`, so use a // local to avoid that. [[maybe_unused]] bool ok = out.ok(); ABSL_ASSUME(!ok); return out; } + +// Same as above, but for rvalue std::string. +#ifndef SWIG +// We use an int in the template parameter to shorten mangled names. +template <int error_code> +Status MakeErrorStringRvalueImpl(std::string&& message, SourceLocation loc); +// Make the instantiations extern to reduce bloat on callers. +extern template Status MakeErrorStringRvalueImpl<0>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<1>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<2>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<3>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<4>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<5>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<6>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<7>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<8>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<9>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<10>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<11>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<12>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<13>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<14>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<15>(std::string&&, + SourceLocation); +extern template Status MakeErrorStringRvalueImpl<16>(std::string&&, + SourceLocation); + +template <StatusCode error_code, typename String> +Status MakeErrorFromStringRvalue(String&& message, SourceLocation loc) { + static_assert(std::is_same_v<String&&, std::string&&>, + "`message` should be std::string&&"); + Status out = MakeErrorStringRvalueImpl<static_cast<int>(error_code)>( + std::forward<String>(message), loc); + // -Wassume warning complains about potential side effects of `ok()`, so use a + // local to avoid that. + [[maybe_unused]] bool ok = out.ok(); + ABSL_ASSUME(!ok); + return out; +} +#endif // SWIG + } // namespace status_internal // Inline implementations to give the compiler static knowledge about the // objects. + +// AbortedError inline Status AbortedError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kAborted>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kAborted>(message, + loc); } + +#ifndef SWIG +template <typename String, typename> +Status AbortedError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kAborted>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// AlreadyExistsError inline Status AlreadyExistsError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kAlreadyExists>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kAlreadyExists>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status AlreadyExistsError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kAlreadyExists>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// CancelledError inline Status CancelledError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kCancelled>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kCancelled>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status CancelledError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kCancelled>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// DataLossError inline Status DataLossError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kDataLoss>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kDataLoss>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status DataLossError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kDataLoss>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// DeadlineExceededError inline Status DeadlineExceededError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kDeadlineExceeded>(message, - loc); + return status_internal::MakeErrorFromStringView< + StatusCode::kDeadlineExceeded>(message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status DeadlineExceededError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue< + StatusCode::kDeadlineExceeded>(std::forward<String>(message), loc); +} +#endif // SWIG + +// FailedPreconditionError inline Status FailedPreconditionError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kFailedPrecondition>(message, - loc); + return status_internal::MakeErrorFromStringView< + StatusCode::kFailedPrecondition>(message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status FailedPreconditionError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue< + StatusCode::kFailedPrecondition>(std::forward<String>(message), loc); +} +#endif // SWIG + +// InternalError inline Status InternalError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kInternal>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kInternal>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status InternalError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kInternal>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// InvalidArgumentError inline Status InvalidArgumentError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kInvalidArgument>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kInvalidArgument>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status InvalidArgumentError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue< + StatusCode::kInvalidArgument>(std::forward<String>(message), loc); +} +#endif // SWIG + +// NotFoundError inline Status NotFoundError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kNotFound>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kNotFound>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status NotFoundError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kNotFound>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// OutOfRangeError inline Status OutOfRangeError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kOutOfRange>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kOutOfRange>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status OutOfRangeError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kOutOfRange>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// PermissionDeniedError inline Status PermissionDeniedError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kPermissionDenied>(message, - loc); + return status_internal::MakeErrorFromStringView< + StatusCode::kPermissionDenied>(message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status PermissionDeniedError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue< + StatusCode::kPermissionDenied>(std::forward<String>(message), loc); +} +#endif // SWIG + +// ResourceExhaustedError inline Status ResourceExhaustedError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kResourceExhausted>(message, - loc); + return status_internal::MakeErrorFromStringView< + StatusCode::kResourceExhausted>(message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status ResourceExhaustedError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue< + StatusCode::kResourceExhausted>(std::forward<String>(message), loc); +} +#endif // SWIG + +// UnauthenticatedError inline Status UnauthenticatedError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kUnauthenticated>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kUnauthenticated>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status UnauthenticatedError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue< + StatusCode::kUnauthenticated>(std::forward<String>(message), loc); +} +#endif // SWIG + +// UnavailableError inline Status UnavailableError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kUnavailable>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kUnavailable>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status UnavailableError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kUnavailable>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// UnimplementedError inline Status UnimplementedError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kUnimplemented>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kUnimplemented>( + message, loc); } + +#ifndef SWIG +template <typename String, typename> +Status UnimplementedError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kUnimplemented>( + std::forward<String>(message), loc); +} +#endif // SWIG + +// UnknownError inline Status UnknownError(absl::string_view message, absl::SourceLocation loc) { - return status_internal::MakeError<StatusCode::kUnknown>(message, loc); + return status_internal::MakeErrorFromStringView<StatusCode::kUnknown>(message, + loc); } +#ifndef SWIG +template <typename String, typename> +Status UnknownError(String&& message, absl::SourceLocation loc) { + return status_internal::MakeErrorFromStringRvalue<StatusCode::kUnknown>( + std::forward<String>(message), loc); +} +#endif // SWIG + ABSL_NAMESPACE_END } // namespace absl
diff --git a/absl/status/status_benchmark.cc b/absl/status/status_benchmark.cc index 0404db1..b001e63 100644 --- a/absl/status/status_benchmark.cc +++ b/absl/status/status_benchmark.cc
@@ -57,4 +57,14 @@ } BENCHMARK(BM_LongMessageRValue); +void BM_LongMessageRValueConvenienceFn(benchmark::State& state) { + for (auto _ : state) { + std::string msg(100, 'X'); + benchmark::DoNotOptimize(msg); + absl::Status s = absl::InvalidArgumentError(std::move(msg)); + benchmark::DoNotOptimize(s); + } +} +BENCHMARK(BM_LongMessageRValueConvenienceFn); + } // namespace
diff --git a/absl/status/status_test.cc b/absl/status/status_test.cc index ddf0be0..c4679d6 100644 --- a/absl/status/status_test.cc +++ b/absl/status/status_test.cc
@@ -19,6 +19,7 @@ #include <array> #include <cstddef> #include <sstream> +#include <string> #include <utility> #include <vector> @@ -46,41 +47,82 @@ } // This structure holds the details for testing a single error code, -// its creator, and its classifier. +// its creator, its rvalue creator, and its classifier. struct ErrorTest { absl::StatusCode code; using Creator = absl::Status (*)(absl::string_view, absl::SourceLocation); - using Classifier = bool (*)(const absl::Status&); Creator creator; + using CreatorRValue = absl::Status (*)(std::string&&, absl::SourceLocation); + CreatorRValue creator_rvalue; + using Classifier = bool (*)(const absl::Status&); Classifier classifier; }; constexpr ErrorTest kErrorTests[]{ - {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled}, - {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown}, - {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError, - absl::IsInvalidArgument}, - {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError, - absl::IsDeadlineExceeded}, - {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound}, - {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError, - absl::IsAlreadyExists}, - {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError, - absl::IsPermissionDenied}, - {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError, - absl::IsResourceExhausted}, - {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError, - absl::IsFailedPrecondition}, - {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted}, - {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange}, - {absl::StatusCode::kUnimplemented, absl::UnimplementedError, - absl::IsUnimplemented}, - {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal}, - {absl::StatusCode::kUnavailable, absl::UnavailableError, - absl::IsUnavailable}, - {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss}, - {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError, - absl::IsUnauthenticated}, + {absl::StatusCode::kCancelled, // + absl::CancelledError, // + absl::CancelledError, // + absl::IsCancelled}, // + {absl::StatusCode::kUnknown, // + absl::UnknownError, // + absl::UnknownError, // + absl::IsUnknown}, // + {absl::StatusCode::kInvalidArgument, // + absl::InvalidArgumentError, // + absl::InvalidArgumentError, // + absl::IsInvalidArgument}, // + {absl::StatusCode::kDeadlineExceeded, // + absl::DeadlineExceededError, // + absl::DeadlineExceededError, // + absl::IsDeadlineExceeded}, // + {absl::StatusCode::kNotFound, // + absl::NotFoundError, // + absl::NotFoundError, // + absl::IsNotFound}, // + {absl::StatusCode::kAlreadyExists, // + absl::AlreadyExistsError, // + absl::AlreadyExistsError, // + absl::IsAlreadyExists}, // + {absl::StatusCode::kPermissionDenied, // + absl::PermissionDeniedError, // + absl::PermissionDeniedError, // + absl::IsPermissionDenied}, // + {absl::StatusCode::kResourceExhausted, // + absl::ResourceExhaustedError, // + absl::ResourceExhaustedError, // + absl::IsResourceExhausted}, // + {absl::StatusCode::kFailedPrecondition, // + absl::FailedPreconditionError, // + absl::FailedPreconditionError, // + absl::IsFailedPrecondition}, // + {absl::StatusCode::kAborted, // + absl::AbortedError, // + absl::AbortedError, // + absl::IsAborted}, // + {absl::StatusCode::kOutOfRange, // + absl::OutOfRangeError, // + absl::OutOfRangeError, // + absl::IsOutOfRange}, // + {absl::StatusCode::kUnimplemented, // + absl::UnimplementedError, // + absl::UnimplementedError, // + absl::IsUnimplemented}, // + {absl::StatusCode::kInternal, // + absl::InternalError, // + absl::InternalError, // + absl::IsInternal}, // + {absl::StatusCode::kUnavailable, // + absl::UnavailableError, // + absl::UnavailableError, // + absl::IsUnavailable}, // + {absl::StatusCode::kDataLoss, // + absl::DataLossError, // + absl::DataLossError, // + absl::IsDataLoss}, // + {absl::StatusCode::kUnauthenticated, // + absl::UnauthenticatedError, // + absl::UnauthenticatedError, // + absl::IsUnauthenticated}, // }; TEST(Status, CreateAndClassify) { @@ -96,9 +138,16 @@ EXPECT_EQ(test.code, status.code()); EXPECT_EQ(message, status.message()); + // Testing the rvalue creator. + absl::Status status_rvalue = test.creator_rvalue( + std::string(message), absl::SourceLocation::current()); + EXPECT_EQ(test.code, status_rvalue.code()); + EXPECT_EQ(message, status_rvalue.message()); + // Ensure that the classifier returns true for a status produced by the // creator. EXPECT_TRUE(test.classifier(status)); + EXPECT_TRUE(test.classifier(status_rvalue)); // Ensure that the classifier returns false for status with a different // code. @@ -111,6 +160,37 @@ } } +// Test that status convenience functions can be called with a string literal. +// Doing so to make sure it's not ambiguous between the string_view and string&& +// overloads. +TEST(Status, StringLiteralCreation) { + EXPECT_EQ(absl::AbortedError("msg").code(), absl::StatusCode::kAborted); + EXPECT_EQ(absl::AlreadyExistsError("msg").code(), + absl::StatusCode::kAlreadyExists); + EXPECT_EQ(absl::CancelledError("msg").code(), absl::StatusCode::kCancelled); + EXPECT_EQ(absl::DataLossError("msg").code(), absl::StatusCode::kDataLoss); + EXPECT_EQ(absl::DeadlineExceededError("msg").code(), + absl::StatusCode::kDeadlineExceeded); + EXPECT_EQ(absl::FailedPreconditionError("msg").code(), + absl::StatusCode::kFailedPrecondition); + EXPECT_EQ(absl::InternalError("msg").code(), absl::StatusCode::kInternal); + EXPECT_EQ(absl::InvalidArgumentError("msg").code(), + absl::StatusCode::kInvalidArgument); + EXPECT_EQ(absl::NotFoundError("msg").code(), absl::StatusCode::kNotFound); + EXPECT_EQ(absl::OutOfRangeError("msg").code(), absl::StatusCode::kOutOfRange); + EXPECT_EQ(absl::PermissionDeniedError("msg").code(), + absl::StatusCode::kPermissionDenied); + EXPECT_EQ(absl::ResourceExhaustedError("msg").code(), + absl::StatusCode::kResourceExhausted); + EXPECT_EQ(absl::UnauthenticatedError("msg").code(), + absl::StatusCode::kUnauthenticated); + EXPECT_EQ(absl::UnavailableError("msg").code(), + absl::StatusCode::kUnavailable); + EXPECT_EQ(absl::UnimplementedError("msg").code(), + absl::StatusCode::kUnimplemented); + EXPECT_EQ(absl::UnknownError("msg").code(), absl::StatusCode::kUnknown); +} + TEST(Status, DefaultConstructor) { absl::Status status; EXPECT_TRUE(status.ok()); @@ -340,37 +420,37 @@ TEST(Status, OstreamOperator) { absl::Status status(absl::StatusCode::kInternal, "fail"); - { std::stringstream stream; + { + std::stringstream stream; stream << status; - EXPECT_THAT(stream.str(), - AllOf(HasSubstr("INTERNAL: fail"), - HasSubstr("status_test.cc:"))); + EXPECT_THAT(stream.str(), AllOf(HasSubstr("INTERNAL: fail"), + HasSubstr("status_test.cc:"))); } status.SetPayload("foo", absl::Cord("bar")); - { std::stringstream stream; + { + std::stringstream stream; stream << status; EXPECT_THAT(stream.str(), AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), HasSubstr("status_test.cc:"))); } status.SetPayload("bar", absl::Cord("\377")); - { std::stringstream stream; + { + std::stringstream stream; stream << status; - EXPECT_THAT(stream.str(), - AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), - HasSubstr("[bar='\\xff']"), - HasSubstr("status_test.cc:"))); + EXPECT_THAT( + stream.str(), + AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), + HasSubstr("[bar='\\xff']"), HasSubstr("status_test.cc:"))); } } TEST(Status, AbslStringify) { absl::Status status(absl::StatusCode::kInternal, "fail"); EXPECT_THAT(absl::StrCat(status), - AllOf(HasSubstr("INTERNAL: fail"), - HasSubstr("status_test.cc:"))); + AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("status_test.cc:"))); EXPECT_THAT(absl::StrFormat("%v", status), - AllOf(HasSubstr("INTERNAL: fail"), - HasSubstr("status_test.cc:"))); + AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("status_test.cc:"))); EXPECT_EQ(absl::StrCat(status), absl::StrFormat("%v", status)); status.SetPayload("foo", absl::Cord("bar")); EXPECT_THAT(absl::StrCat(status), @@ -379,8 +459,7 @@ status.SetPayload("bar", absl::Cord("\377")); EXPECT_THAT(absl::StrCat(status), AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), - HasSubstr("[bar='\\xff']"), - HasSubstr("status_test.cc:"))); + HasSubstr("[bar='\\xff']"), HasSubstr("status_test.cc:"))); } TEST(Status, OstreamEqStringify) { @@ -867,8 +946,7 @@ { // Status that ignores source location. absl::Status status_ignores_source_location[] = { - absl::Status(), - absl::Status(absl::StatusCode::kInternal, "")}; + absl::Status(), absl::Status(absl::StatusCode::kInternal, "")}; for (absl::Status& s : status_ignores_source_location) { for (int i = 0; i < max_iter; ++i) { s.AddSourceLocation(absl::SourceLocation::current()); @@ -967,27 +1045,27 @@ s.SetPayload("bar", absl::Cord("\377")); - EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything), - AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), - HasSubstr("[bar='\\xff']"), - HasSubstr(source_location_string), - HasSubstr(source_location_stack))); - EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload | - absl::StatusToStringMode::kWithSourceLocation), - AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), - HasSubstr("[bar='\\xff']"), - HasSubstr(source_location_string), - HasSubstr(source_location_stack))); - EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithSourceLocation), - AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")), - Not(HasSubstr("[bar='\\xff']")), - HasSubstr(source_location_string), - HasSubstr(source_location_stack))); - EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload), - AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), - HasSubstr("[bar='\\xff']"), - Not(HasSubstr(source_location_string)), - Not(HasSubstr(source_location_stack)))); + EXPECT_THAT( + s.ToString(absl::StatusToStringMode::kWithEverything), + AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), + HasSubstr("[bar='\\xff']"), HasSubstr(source_location_string), + HasSubstr(source_location_stack))); + EXPECT_THAT( + s.ToString(absl::StatusToStringMode::kWithPayload | + absl::StatusToStringMode::kWithSourceLocation), + AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), + HasSubstr("[bar='\\xff']"), HasSubstr(source_location_string), + HasSubstr(source_location_stack))); + EXPECT_THAT( + s.ToString(absl::StatusToStringMode::kWithSourceLocation), + AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")), + Not(HasSubstr("[bar='\\xff']")), HasSubstr(source_location_string), + HasSubstr(source_location_stack))); + EXPECT_THAT( + s.ToString(absl::StatusToStringMode::kWithPayload), + AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), + HasSubstr("[bar='\\xff']"), Not(HasSubstr(source_location_string)), + Not(HasSubstr(source_location_stack)))); } TEST(Status, StackTracePayloadOverflow) {