fork download
  1. #include <system_error>
  2. #include <type_traits>
  3. #include <new>
  4.  
  5. // #define USE_OUTCOME
  6. // #define USE_ERROR
  7.  
  8. // BOOST_NOINLINE ---------------------------------------------//
  9. // Macro to use in place of 'inline' to prevent a function to be inlined
  10. #if !defined(BOOST_NOINLINE)
  11. # if defined(_MSC_VER)
  12. # define BOOST_NOINLINE __declspec(noinline)
  13. # elif defined(__GNUC__) && __GNUC__ > 3
  14. // Clang also defines __GNUC__ (as 4)
  15. # if defined(__CUDACC__)
  16. // nvcc doesn't always parse __noinline__,
  17. // see: https://s...content-available-to-author-only...t.org/trac/boost/ticket/9392
  18. # define BOOST_NOINLINE __attribute__ ((noinline))
  19. # else
  20. # define BOOST_NOINLINE __attribute__ ((__noinline__))
  21. # endif
  22. # else
  23. # define BOOST_NOINLINE
  24. # endif
  25. #endif
  26.  
  27. #ifdef USE_OUTCOME
  28. #include <boost/outcome/monad.hpp>
  29.  
  30. using namespace BOOST_OUTCOME_V1_NAMESPACE;
  31. #else
  32.  
  33. class not_an_error_category_impl : public std::error_category
  34. {
  35. public:
  36. virtual const char* name() const noexcept { return ""; }
  37. virtual std::string message( int ev ) const { return std::string{}; }
  38. virtual std::error_condition default_error_condition( int ev ) const noexcept {
  39. return std::error_condition( ev, *this );
  40. }
  41. };
  42.  
  43. not_an_error_category_impl instance;
  44.  
  45. inline const std::error_category& not_an_error_category()
  46. {
  47. return instance;
  48. }
  49.  
  50. template< typename T >
  51. struct result {
  52. typedef typename std::aligned_storage<sizeof( T ), alignof(T)>::type value_store;
  53. value_store value;
  54. std::error_code error;
  55.  
  56. result( const T& x ) {
  57. error.assign( 0, not_an_error_category() );
  58. new(&value) T( x );
  59. }
  60.  
  61. result( T&& x ) {
  62. error.assign( 0, not_an_error_category() );
  63. new(&value) T( std::move( x ) );
  64. }
  65.  
  66. result( std::error_code x ) : error( x ) {
  67. }
  68.  
  69. ~result() {
  70. destroy<T>();
  71. }
  72.  
  73. result( const result& rhs ) {
  74. copy<T>( rhs );
  75. }
  76.  
  77. result( result&& rhs ) {
  78. move<T>( std::move( rhs ) );
  79. }
  80.  
  81. explicit operator bool() const {
  82. return (&error.category() == &not_an_error_category());
  83. }
  84.  
  85. T& get() {
  86. return *reinterpret_cast<T*>(&value);
  87. }
  88.  
  89. template< typename U >
  90. typename std::enable_if<std::is_trivially_destructible<U>::value>::type destroy() {}
  91. template< typename U >
  92. typename std::enable_if<!std::is_trivially_destructible<U>::value>::type destroy() {
  93. if ( *this ) {
  94. get().~T();
  95. }
  96. }
  97.  
  98. template< typename U >
  99. typename std::enable_if<std::is_trivially_copyable<U>::value>::type copy( const result<T>& rhs ) {
  100. value = rhs.value;
  101. error = rhs.error;
  102. }
  103. template< typename U >
  104. typename std::enable_if<!std::is_trivially_copyable<U>::value>::type copy( const result<T>& rhs ) {
  105. destroy<T>();
  106. if ( rhs ) {
  107. new(&value) T( rhs.value );
  108. }
  109. error = rhs.error;
  110. }
  111.  
  112. template< typename U >
  113. typename std::enable_if<std::is_trivially_move_constructible<U>::value>::type move( result<T>&& rhs ) {
  114. value = rhs.value;
  115. error = rhs.error;
  116. }
  117. template< typename U >
  118. typename std::enable_if<!std::is_trivially_move_constructible<U>::value>::type move( result<T>&& rhs ) {
  119. destroy<T>();
  120. if ( rhs ) {
  121. new(&value) T( std::move( rhs.value ) );
  122. }
  123. error = rhs.error;
  124. }
  125. };
  126. #endif
  127.  
  128. BOOST_NOINLINE result<int> bar()
  129. {
  130. #ifdef USE_ERROR
  131. return std::make_error_code( std::errc::bad_address );
  132. #else
  133. return 1;
  134. #endif
  135. }
  136.  
  137. int main()
  138. {
  139. result<int> _foo = bar();
  140. int foo = 0;
  141. if ( _foo ) {
  142. foo = _foo.get();
  143. }
  144. return foo;
  145. }
  146.  
Runtime error #stdin #stdout 0s 3452KB
stdin
Standard input is empty
stdout
Standard output is empty