]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Simplify std::error_code and std::error_condition
authorJonathan Wakely <jwakely@redhat.com>
Fri, 26 Aug 2022 11:55:02 +0000 (12:55 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 26 Aug 2022 14:29:03 +0000 (15:29 +0100)
This removes the redundant operator=(E) from std::error_code and
std::error_condition. Without that overload, assignment from a custom
type will use the templated constructor to create a temporary and then
use the trivial copy assignment operator. With the overloaded
assignment, we have to check the constraints twice as often, because
that overload and its constraints are checked for simple copy
assignments (including the one in the overloaded assignment operator
itself!)

Also add tests that ADL is used as per LWG 3629.

libstdc++-v3/ChangeLog:

* include/std/system_error (error_code::_Check): New alias
template for constructor SFINAE constraint.
(error_code::error_code(ErrorCodeEnum)): Use it.
(error_code::operator=(ErrorCodeEnum)): Remove.
(error_condition::_Check): New alias template for constraint.
(error_condition::error_condition(ErrorConditionEnum)): Use it.
(error_condition::operator=(ErrorConditionEnum)): Remove.
* testsuite/19_diagnostics/error_code/cons/1.cc: Check
constructor taking user-defined error enum.
* testsuite/19_diagnostics/error_condition/cons/1.cc: Likewise.

libstdc++-v3/include/std/system_error
libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc
libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc

index 87cf720f6e396b1ced58021da4532ec75090eae1..050439427cc410332413dd8a44780ac388e22655 100644 (file)
@@ -216,6 +216,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
    */
   class error_code
   {
+    template<typename _ErrorCodeEnum>
+      using _Check
+       = __enable_if_t<is_error_code_enum<_ErrorCodeEnum>::value>;
+
   public:
     error_code() noexcept
     : _M_value(0), _M_cat(&system_category()) { }
@@ -223,11 +227,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     error_code(int __v, const error_category& __cat) noexcept
     : _M_value(__v), _M_cat(&__cat) { }
 
-    template<typename _ErrorCodeEnum, typename = typename
-            enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
+    /// Initialize with a user-defined type, by calling make_error_code.
+    template<typename _ErrorCodeEnum,
+            typename = _Check<_ErrorCodeEnum>>
       error_code(_ErrorCodeEnum __e) noexcept
       { *this = make_error_code(__e); }
 
+    error_code(const error_code&) = default;
+    error_code& operator=(const error_code&) = default;
+
     void
     assign(int __v, const error_category& __cat) noexcept
     {
@@ -239,13 +247,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     clear() noexcept
     { assign(0, system_category()); }
 
-    // DR 804.
-    template<typename _ErrorCodeEnum>
-      typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
-                        error_code&>::type
-      operator=(_ErrorCodeEnum __e) noexcept
-      { return *this = make_error_code(__e); }
-
     /// The error value.
     [[__nodiscard__]]
     int
@@ -345,6 +346,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
    */
   class error_condition
   {
+    template<typename _ErrorConditionEnum>
+      using _Check
+       = __enable_if_t<is_error_condition_enum<_ErrorConditionEnum>::value>;
+
   public:
     /// Initialize with a zero (no error) value and the generic category.
     error_condition() noexcept
@@ -354,11 +359,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     error_condition(int __v, const error_category& __cat) noexcept
     : _M_value(__v), _M_cat(&__cat) { }
 
-    template<typename _ErrorConditionEnum, typename = typename
-        enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
+    /// Initialize with a user-defined type, by calling make_error_condition.
+    template<typename _ErrorConditionEnum,
+            typename = _Check<_ErrorConditionEnum>>
       error_condition(_ErrorConditionEnum __e) noexcept
       { *this = make_error_condition(__e); }
 
+    error_condition(const error_condition&) = default;
+    error_condition& operator=(const error_condition&) = default;
+
     /// Set the value and category.
     void
     assign(int __v, const error_category& __cat) noexcept
@@ -367,13 +376,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       _M_cat = &__cat;
     }
 
-    // DR 804.
-    template<typename _ErrorConditionEnum>
-      typename enable_if<is_error_condition_enum
-                        <_ErrorConditionEnum>::value, error_condition&>::type
-      operator=(_ErrorConditionEnum __e) noexcept
-      { return *this = make_error_condition(__e); }
-
     /// Reset the value and category to the default-constructed state.
     void
     clear() noexcept
index f454fc270d85622a44ea2a0b3343410018e0e719..d48d5c1ffe87aa680945193e49eb1459a4b47edf 100644 (file)
 #include <system_error>
 #include <testsuite_error.h>
 
+namespace adl
+{
+  struct Error { };
+
+  const Error err;
+
+  struct category : std::error_category
+  {
+    const char* name() const noexcept override { return "adl"; }
+    std::string message(int) const { return ""; }
+  };
+
+  const category cat;
+
+  std::error_code
+  make_error_code(Error) { return std::error_code(999, cat); }
+}
+
+template<> struct std::is_error_code_enum<adl::Error> : std::true_type { };
+
 int main()
 {
-  // 1
+  // 1 error_code()
   std::error_code e1;
   VERIFY( e1.value() == 0 );
   VERIFY( e1.category() == std::system_category() );
 
-  // 2
+  // 2 error_code(int, const error_category&)
   const __gnu_test::test_category cat;
   std::error_code e2(e1.value(), cat);
   VERIFY( e2.value() == e1.value() );
   VERIFY( e2.category() == cat );
 
-  // 3
+  // 3 error_code(const error_code&)
   std::error_code e3(std::make_error_code(std::errc::operation_not_supported));
   VERIFY( e3.value() == int(std::errc::operation_not_supported) );
   VERIFY( e3.category() == std::generic_category() );
 
-  return 0;
+  // 4 error_code(ErrorCodeEnum)
+  std::error_code e4(adl::err);
+  VERIFY( e4.value() == 999 );
+  VERIFY( e4.category() == adl::cat );
 }
index 1e039c45b1d6bad8b30ec7d5c68fc0278ef6b54d..c353b0266ee2f87e9b3fca645965722b3aa2b70d 100644 (file)
 #include <system_error>
 #include <testsuite_error.h>
 
+namespace adl
+{
+  struct Error { };
+
+  const Error err;
+
+  struct category : std::error_category
+  {
+    const char* name() const noexcept override { return "adl"; }
+    std::string message(int) const { return ""; }
+  };
+
+  const category cat;
+
+  std::error_condition
+  make_error_condition(Error) { return std::error_condition(999, cat); }
+}
+
+template<> struct std::is_error_condition_enum<adl::Error> : std::true_type { };
+
 void test01()
 {
-  // 1
+  // 1 error_condition()
   std::error_condition e1;
   VERIFY( e1.value() == 0 );
   VERIFY( e1.category() == std::generic_category() );
 
-  // 2
+  // 2 error_condition(int, const error_category&)
   const __gnu_test::test_category cat;
   std::error_condition e2(e1.value(), cat);
   VERIFY( e2.value() == e1.value() );
   VERIFY( e2.category() == cat );
 
-  // 3
+  // 3 error_condition(const error_condition&)
   std::error_condition e3(std::errc::operation_not_supported);
   VERIFY( e3.value() == int(std::errc::operation_not_supported) );
   VERIFY( e3.category() == std::generic_category() );
+
+  // 4 error_condition(ErrorConditionEnum)
+  std::error_condition e4(adl::err);
+  VERIFY( e4.value() == 999 );
+  VERIFY( e4.category() == adl::cat );
 }
 
 int main()