folly::TryException inherits from std::logic_error, like std::bad_optional_access...
authorEric Niebler <eniebler@fb.com>
Thu, 29 Dec 2016 19:51:18 +0000 (11:51 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 29 Dec 2016 20:03:05 +0000 (12:03 -0800)
Summary:
folly::TryException was inheriting from std::exception and managing its own message in a std::string data member.
That is suboptimal for the following reasons:

1) The analagous std:: type, std::bad_optional_access, inherits from std::logic_error. According to the Principle of Least
   Astonishment, folly::TryException should follow suit.
2) std::logic_error has a nothrow copy constructor. (This is typically implemented with a ref-counted string.)
   std::string does not. By explicitly managing its own message, folly::TryException picks up a throwing copy
   constructor. Exception classes should try to be nothrow copyable.
3) With most stdlib implementations, std::string is larger by a lot than the std:: exceptions. By changing
   folly::TryException as suggested, its size drops from 40 bytes to 16 on clang and gcc >=5.0.

Reviewed By: yfeldblum

Differential Revision: D4368760

fbshipit-source-id: 327f78f428419ccf9c7af3e0f57cc478d147fb37

folly/Try.h

index e6b6ebad3298450c5f4fa6f001fd751fd79c849b..1f08e27e3a6fca3160679b13217394fc9f3ef4b1 100644 (file)
 
 #pragma once
 
-#include <type_traits>
-#include <exception>
-#include <algorithm>
 #include <folly/ExceptionWrapper.h>
 #include <folly/Likely.h>
 #include <folly/Memory.h>
 #include <folly/Portability.h>
 #include <folly/Unit.h>
+#include <exception>
+#include <stdexcept>
+#include <type_traits>
+#include <utility>
 
 namespace folly {
 
-class TryException : public std::exception {
+class TryException : public std::logic_error {
  public:
-  explicit TryException(std::string message_arg) noexcept
-      : message(std::move(message_arg)) {}
-
-  const char* what() const noexcept override {
-    return message.c_str();
-  }
-
-  bool operator==(const TryException& other) const noexcept {
-    return other.message == this->message;
-  }
-
-  bool operator!=(const TryException& other) const noexcept {
-    return !(*this == other);
-  }
-
- protected:
-  std::string message;
+  using std::logic_error::logic_error;
 };
 
 class UsingUninitializedTry : public TryException {
  public:
-  UsingUninitializedTry() noexcept : TryException("Using unitialized try") {}
+  UsingUninitializedTry() : TryException("Using unitialized try") {}
 };
 
 /*