Backport
any.hpp
Go to the documentation of this file.
1 
7 /*
8  The MIT License (MIT)
9 
10  Copyright (c) 2020 Matthew Rodusek All rights reserved.
11 
12  Permission is hereby granted, free of charge, to any person obtaining a copy
13  of this software and associated documentation files (the "Software"), to deal
14  in the Software without restriction, including without limitation the rights
15  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  copies of the Software, and to permit persons to whom the Software is
17  furnished to do so, subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be included in
20  all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  SOFTWARE.
29 */
30 #ifndef BPSTD_ANY_HPP
31 #define BPSTD_ANY_HPP
32 
33 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
34 # pragma once
35 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
36 
37 #include "detail/config.hpp"
38 #include "type_traits.hpp" // enable_if_t, is_*
39 #include "utility.hpp" // in_place_type_t, move, forward
40 
41 #include <typeinfo> // std::bad_cast, std::type_info
42 #include <initializer_list> // std::initializer_list
43 #include <new> // placement-new
44 #include <cassert> // assert
45 
46 BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
47 
48 namespace bpstd {
49 
50  class any;
51 
52  //============================================================================
53  // class : bad_any_cast
54  //============================================================================
55 
56  class bad_any_cast : public std::bad_cast
57  {
58  const char* what() const noexcept override;
59  };
60 
61  //============================================================================
62  // class : any
63  //============================================================================
64 
84  class any
85  {
86  //--------------------------------------------------------------------------
87  // Constructors / Destructor / Assignment
88  //--------------------------------------------------------------------------
89  public:
90 
92  any() noexcept;
93 
99  any(any&& other) noexcept;
100 
104  any(const any& other);
105 
109  template<typename ValueType,
110  typename=enable_if_t<!is_same<decay_t<ValueType>,any>::value &&
111  is_copy_constructible<decay_t<ValueType>>::value>>
112  // cppcheck-suppress noExplicitConstructor
113  any(ValueType&& value);
114 
122  template<typename ValueType, typename...Args,
123  typename=enable_if_t<is_constructible<decay_t<ValueType>,Args...>::value &&
124  is_copy_constructible<decay_t<ValueType>>::value>>
125  explicit any(in_place_type_t<ValueType>, Args&&...args);
126 
135  template<typename ValueType, typename U, typename...Args,
136  typename=enable_if_t<is_constructible<decay_t<ValueType>,std::initializer_list<U>,Args...>::value &&
137  is_copy_constructible<decay_t<ValueType>>::value>>
139  std::initializer_list<U> il,
140  Args&&...args);
141 
142  //--------------------------------------------------------------------------
143 
144  ~any();
145 
146  //--------------------------------------------------------------------------
147 
152  any& operator=(any&& other) noexcept;
153 
158  any& operator=(const any& other);
159 
164  template<typename ValueType,
165  typename=enable_if_t<!is_same<decay_t<ValueType>,any>::value &&
166  is_copy_constructible<decay_t<ValueType>>::value>>
167  any& operator=(ValueType&& value);
168 
169  //--------------------------------------------------------------------------
170  // Modifiers
171  //--------------------------------------------------------------------------
172  public:
173 
181  template<typename ValueType, typename...Args,
182  typename=enable_if_t<is_constructible<decay_t<ValueType>,Args...>::value &&
183  is_copy_constructible<decay_t<ValueType>>::value>>
184  decay_t<ValueType>& emplace(Args&&...args);
185  template<typename ValueType, typename U, typename...Args,
186  typename=enable_if_t<is_constructible<decay_t<ValueType>,std::initializer_list<U>,Args...>::value &&
187  is_copy_constructible<decay_t<ValueType>>::value>>
188  decay_t<ValueType>& emplace(std::initializer_list<U> il, Args&&...args );
190 
193  void reset() noexcept;
194 
201  void swap(any& other) noexcept;
202 
203  //--------------------------------------------------------------------------
204  // Observers
205  //--------------------------------------------------------------------------
206  public:
207 
211  bool has_value() const noexcept;
212 
217  const std::type_info& type() const noexcept;
218 
219  //--------------------------------------------------------------------------
220  // Private Static Members / Types
221  //--------------------------------------------------------------------------
222  private:
223 
224  // Internal buffer size + alignment
225  static constexpr auto buffer_size = 4u * sizeof(void*);
226  static constexpr auto buffer_align = alignof(void*);
227 
228  // buffer (for internal storage)
229  using internal_buffer = typename aligned_storage<buffer_size,buffer_align>::type;
230 
231  union storage
232  {
233  internal_buffer internal;
234  void* external;
235  };
236 
237  //--------------------------------------------------------------------------
238 
239  // trait to determine if internal storage is required
240  template<typename T>
241  using requires_internal_storage = bool_constant<
242  (sizeof(T) <= buffer_size) &&
243  ((buffer_align % alignof(T)) == 0) &&
244  is_nothrow_move_constructible<T>::value
245  >;
246 
247  //-----------------------------------------------------------------------
248 
249  template<typename T>
250  struct internal_storage_handler;
251 
252  template<typename T>
253  struct external_storage_handler;
254 
255  template<typename T>
256  using storage_handler = conditional_t<
257  requires_internal_storage<T>::value,
258  internal_storage_handler<T>,
259  external_storage_handler<T>
260  >;
261 
262  //-----------------------------------------------------------------------
263 
264  enum class operation
265  {
266  destroy,
267  copy,
268  move,
269  value,
270  type,
271  };
272 
273  //-----------------------------------------------------------------------
274 
275  using storage_handler_ptr = const void*(*)(operation, const storage*,const storage*);
276 
277  template<typename T>
278  friend T* any_cast(any*) noexcept;
279  template<typename T>
280  friend const T* any_cast(const any*) noexcept;
281 
282  //-----------------------------------------------------------------------
283  // Private Members
284  //-----------------------------------------------------------------------
285  private:
286 
287  storage m_storage;
288  storage_handler_ptr m_storage_handler;
289  };
290 
291  //=========================================================================
292  // non-member functions : class : any
293  //=========================================================================
294 
295  //-------------------------------------------------------------------------
296  // utilities
297  //-------------------------------------------------------------------------
298 
300  void swap(any& lhs, any& rhs) noexcept;
301 
302  //-------------------------------------------------------------------------
303  // casts
304  //-------------------------------------------------------------------------
305 
312  template<typename T>
313  T any_cast(any& operand);
314  template<typename T>
315  T any_cast(any&& operand);
316  template<typename T>
317  T any_cast(const any& operand);
319 
325  template<typename T>
326  T* any_cast(any* operand) noexcept;
327  template<typename T>
328  const T* any_cast(const any* operand) noexcept;
330 
331 } // namespace bpstd
332 
333 //=============================================================================
334 // definitions : class : bad_any_cast
335 //=============================================================================
336 
337 inline
338 const char* bpstd::bad_any_cast::what()
339  const noexcept
340 {
341  return "bad_any_cast";
342 }
343 
344 //=============================================================================
345 // class : any::internal_storage_handler
346 //=============================================================================
347 
348 template<typename T>
349 struct bpstd::any::internal_storage_handler
350 {
351  template<typename...Args>
352  static T* construct(storage& s, Args&&...args);
353 
354  template<typename U, typename...Args>
355  static T* construct(storage& s, std::initializer_list<U> il, Args&&...args);
356 
357  static void destroy(storage& s);
358 
359  static const void* handle(operation op,
360  const storage* self,
361  const storage* other);
362 };
363 
364 //=============================================================================
365 // definition : class : any::internal_storage_handler
366 //=============================================================================
367 
368 template<typename T>
369 template<typename...Args>
370 inline BPSTD_INLINE_VISIBILITY
371 T* bpstd::any::internal_storage_handler<T>
372  ::construct(storage& s, Args&&...args)
373 {
374  return ::new(&s.internal) T(bpstd::forward<Args>(args)...);
375 }
376 
377 template<typename T>
378 template<typename U, typename...Args>
379 inline BPSTD_INLINE_VISIBILITY
380 T* bpstd::any::internal_storage_handler<T>
381  ::construct(storage& s, std::initializer_list<U> il, Args&&...args)
382 {
383  return ::new(&s.internal) T(il, bpstd::forward<Args>(args)...);
384 }
385 
386 template<typename T>
387 inline BPSTD_INLINE_VISIBILITY
388 void bpstd::any::internal_storage_handler<T>
389  ::destroy(storage& s)
390 {
391  auto* t = static_cast<T*>(static_cast<void*>(&s.internal));
392  t->~T();
393 }
394 
395 template<typename T>
396 inline BPSTD_INLINE_VISIBILITY
397 const void* bpstd::any::internal_storage_handler<T>
398  ::handle(operation op,
399  const storage* self,
400  const storage* other)
401 {
402  switch (op)
403  {
404  case operation::destroy:
405  {
406  assert(self != nullptr);
407  BPSTD_UNUSED(other);
408 
409  destroy(const_cast<storage&>(*self));
410  break;
411  }
412 
413  case operation::copy:
414  {
415  assert(self != nullptr);
416  assert(other != nullptr);
417 
418  // Copy construct from the internal storage
419  const auto* p = reinterpret_cast<const T*>(&other->internal);
420  construct( const_cast<storage&>(*self), *p);
421  break;
422  }
423 
424  case operation::move:
425  {
426  assert(self != nullptr);
427  assert(other != nullptr);
428 
429  // Move construct from the internal storage. '
430  const auto* p = reinterpret_cast<const T*>(&other->internal);
431  construct(const_cast<storage&>(*self), bpstd::move(*const_cast<T*>(p)));
432  break;
433  }
434 
435  case operation::value:
436  {
437  assert(self != nullptr);
438  BPSTD_UNUSED(other);
439 
440  // NOTE(bitwize): This seemingly arbitrary conversion is for proper
441  // type-safety/correctness. Otherwise, converting an aligned_storage_t*
442  // to void* and then to T* would violate strict-aliasing -- which
443  // would be undefined-behavior. Behavior is only well-defined for
444  // casts from void* to T* if the the void* originated from a T*.
445  const auto* p = reinterpret_cast<const T*>(&self->internal);
446  return static_cast<const void*>(p);
447  }
448 
449  case operation::type:
450  {
451  BPSTD_UNUSED(self);
452  BPSTD_UNUSED(other);
453 
454  return static_cast<const void*>(&typeid(T));
455  }
456  }
457  return nullptr;
458 }
459 
460 //=============================================================================
461 // class : any::external_storage_handler
462 //=============================================================================
463 
464 template<typename T>
465 struct bpstd::any::external_storage_handler
466 {
467  template<typename...Args>
468  static T* construct(storage& s, Args&&...args);
469 
470  template<typename U, typename...Args>
471  static T* construct(storage& s, std::initializer_list<U> il, Args&&...args);
472 
473  static void destroy(storage& s);
474 
475  static const void* handle(operation op,
476  const storage* self,
477  const storage* other);
478 };
479 
480 
481 //=============================================================================
482 // definition : class : any::external_storage_handler
483 //=============================================================================
484 
485 template<typename T>
486 template<typename...Args>
487 inline BPSTD_INLINE_VISIBILITY
488 T* bpstd::any::external_storage_handler<T>
489  ::construct(storage& s, Args&&...args)
490 {
491  s.external = new T(bpstd::forward<Args>(args)...);
492  return static_cast<T*>(s.external);
493 }
494 
495 template<typename T>
496 template<typename U, typename...Args>
497 inline BPSTD_INLINE_VISIBILITY
498 T* bpstd::any::external_storage_handler<T>
499  ::construct(storage& s, std::initializer_list<U> il, Args&&...args)
500 {
501  s.external = new T(il, bpstd::forward<Args>(args)...);
502  return static_cast<T*>(s.external);
503 }
504 
505 template<typename T>
506 inline BPSTD_INLINE_VISIBILITY
507 void bpstd::any::external_storage_handler<T>
508  ::destroy(storage& s)
509 {
510  delete static_cast<T*>(s.external);
511 }
512 
513 template<typename T>
514 inline BPSTD_INLINE_VISIBILITY
515 const void* bpstd::any::external_storage_handler<T>
516  ::handle( operation op,
517  const storage* self,
518  const storage* other )
519 {
520  switch (op)
521  {
522  case operation::destroy:
523  {
524  assert(self != nullptr);
525  BPSTD_UNUSED(other);
526 
527  destroy(const_cast<storage&>(*self));
528  break;
529  }
530 
531  case operation::copy:
532  {
533  assert(self != nullptr);
534  assert(other != nullptr);
535 
536  // Copy construct from the internal storage
537  construct( const_cast<storage&>(*self),
538  *static_cast<const T*>(other->external));
539  break;
540  }
541 
542  case operation::move:
543  {
544  BPSTD_UNUSED(self != nullptr);
545  assert(other != nullptr);
546 
547  const auto p = static_cast<const T*>(other->external);
548  // Move construct from the internal storage. '
549  construct(const_cast<storage&>(*self), bpstd::move(*const_cast<T*>(p)));
550  break;
551  }
552 
553  case operation::value:
554  {
555  assert(self != nullptr);
556  BPSTD_UNUSED(other);
557 
558  // self->external was already created as a T*; no need to cast like in
559  // internal.
560  return self->external;
561  }
562 
563  case operation::type:
564  {
565  BPSTD_UNUSED(self);
566  BPSTD_UNUSED(other);
567 
568  return &typeid(T);
569  }
570  }
571  return nullptr;
572 }
573 
574 //=============================================================================
575 // definitions : class : any
576 //=============================================================================
577 
578 //-----------------------------------------------------------------------------
579 // Constructors / Destructor / Assignment
580 //-----------------------------------------------------------------------------
581 
582 inline BPSTD_INLINE_VISIBILITY
584  noexcept
585  : m_storage{},
586  m_storage_handler{nullptr}
587 {
588 
589 }
590 
591 inline BPSTD_INLINE_VISIBILITY
593  noexcept
594  : m_storage{},
595  m_storage_handler{other.m_storage_handler}
596 {
597  if (m_storage_handler != nullptr) {
598  m_storage_handler(operation::move, &m_storage, &other.m_storage);
599  }
600 }
601 
602 inline BPSTD_INLINE_VISIBILITY
603 bpstd::any::any(const any& other)
604  : m_storage{},
605  m_storage_handler{nullptr}
606 {
607 
608  if (other.m_storage_handler != nullptr) {
609  // Set handler after constructing, in case of exception
610  const auto handler = other.m_storage_handler;
611 
612  handler(operation::copy, &m_storage, &other.m_storage);
613  m_storage_handler = handler;
614  }
615 }
616 
617 template<typename ValueType, typename>
618 inline BPSTD_INLINE_VISIBILITY
619 bpstd::any::any(ValueType&& value)
620  : m_storage{},
621  m_storage_handler{nullptr}
622 {
623  // Set handler after constructing, in case of exception
624  using handler_type = storage_handler<decay_t<ValueType>>;
625 
626  handler_type::construct(m_storage, bpstd::forward<ValueType>(value));
627  m_storage_handler = &handler_type::handle;
628 }
629 
630 template<typename ValueType, typename...Args, typename>
631 inline BPSTD_INLINE_VISIBILITY
632 bpstd::any::any(in_place_type_t<ValueType>, Args&&...args)
633  : m_storage{},
634  m_storage_handler{nullptr}
635 {
636  // Set handler after constructing, in case of exception
637  using handler_type = storage_handler<decay_t<ValueType>>;
638 
639  handler_type::construct(m_storage, bpstd::forward<Args>(args)...);
640  m_storage_handler = &handler_type::handle;
641 }
642 
643 template<typename ValueType, typename U, typename...Args, typename>
644 inline BPSTD_INLINE_VISIBILITY
645 bpstd::any::any(in_place_type_t<ValueType>,
646  std::initializer_list<U> il,
647  Args&&...args)
648  : m_storage{},
649  m_storage_handler{nullptr}
650 {
651  // Set handler after constructing, in case of exception
652  using handler_type = storage_handler<decay_t<ValueType>>;
653 
654  handler_type::construct(m_storage, il, bpstd::forward<Args>(args)...);
655  m_storage_handler = &handler_type::handle;
656 }
657 
658 //-----------------------------------------------------------------------------
659 
660 inline BPSTD_INLINE_VISIBILITY
661 bpstd::any::~any()
662 {
663  reset();
664 }
665 
666 //-----------------------------------------------------------------------------
667 
668 inline BPSTD_INLINE_VISIBILITY
670  noexcept
671 {
672  reset();
673 
674  if (other.m_storage_handler != nullptr) {
675  m_storage_handler = other.m_storage_handler;
676  m_storage_handler(operation::move, &m_storage, &other.m_storage);
677  }
678 
679  return (*this);
680 }
681 
682 inline BPSTD_INLINE_VISIBILITY
684 {
685  reset();
686 
687  if (other.m_storage_handler != nullptr) {
688  // Set handler after constructing, in case of exception
689  const auto handler = other.m_storage_handler;
690 
691  handler(operation::copy, &m_storage, &other.m_storage);
692  m_storage_handler = handler;
693  }
694 
695  return (*this);
696 }
697 
698 template<typename ValueType, typename>
699 inline BPSTD_INLINE_VISIBILITY
700 bpstd::any& bpstd::any::operator=(ValueType&& value)
701 {
702  using handler_type = storage_handler<decay_t<ValueType>>;
703 
704  reset();
705 
706  handler_type::construct(m_storage, bpstd::forward<ValueType>(value));
707  m_storage_handler = &handler_type::handle;
708 
709  return (*this);
710 }
711 
712 //-----------------------------------------------------------------------------
713 // Modifiers
714 //-----------------------------------------------------------------------------
715 
716 template<typename ValueType, typename...Args, typename>
717 inline BPSTD_INLINE_VISIBILITY
718 bpstd::decay_t<ValueType>&
719  bpstd::any::emplace(Args&&...args)
720 {
721  using handler_type = storage_handler<decay_t<ValueType>>;
722 
723  reset();
724 
725  auto& result = *handler_type::construct(m_storage,
726  bpstd::forward<Args>(args)...);
727  m_storage_handler = &handler_type::handle;
728 
729  return result;
730 }
731 
732 template<typename ValueType, typename U, typename...Args, typename>
733 inline BPSTD_INLINE_VISIBILITY
734 bpstd::decay_t<ValueType>&
735  bpstd::any::emplace(std::initializer_list<U> il,
736  Args&&...args)
737 {
738  using handler_type = storage_handler<decay_t<ValueType>>;
739 
740  reset();
741 
742  auto& result = *handler_type::construct(m_storage,
743  il,
744  bpstd::forward<Args>(args)...);
745  m_storage_handler = &handler_type::handle;
746 
747  return result;
748 }
749 
750 inline BPSTD_INLINE_VISIBILITY
752  noexcept
753 {
754  if (m_storage_handler != nullptr) {
755  m_storage_handler(operation::destroy, &m_storage, nullptr);
756  m_storage_handler = nullptr;
757  }
758 }
759 
760 inline BPSTD_INLINE_VISIBILITY
761 void bpstd::any::swap(any& other)
762  noexcept
763 {
764  using std::swap;
765 
766  if (m_storage_handler != nullptr && other.m_storage_handler != nullptr)
767  {
768  auto tmp = any{};
769 
770  // tmp := self
771  tmp.m_storage_handler = m_storage_handler;
772  m_storage_handler(operation::move, &tmp.m_storage, &m_storage);
773  m_storage_handler(operation::destroy, &m_storage, nullptr);
774 
775  // self := other
776  m_storage_handler = other.m_storage_handler;
777  m_storage_handler(operation::move, &m_storage, &other.m_storage);
778  m_storage_handler(operation::destroy, &other.m_storage, nullptr);
779 
780  // other := tmp
781  other.m_storage_handler = tmp.m_storage_handler;
782  other.m_storage_handler(operation::move, &other.m_storage, &tmp.m_storage);
783  }
784  else if (other.m_storage_handler != nullptr)
785  {
786  swap(m_storage_handler, other.m_storage_handler);
787 
788  // self := other
789  m_storage_handler(operation::move, &m_storage, &other.m_storage);
790  m_storage_handler(operation::destroy, &other.m_storage, nullptr);
791  }
792  else if (m_storage_handler != nullptr)
793  {
794  swap(m_storage_handler, other.m_storage_handler);
795 
796  // other := self
797  other.m_storage_handler(operation::move, &other.m_storage, &m_storage);
798  other.m_storage_handler(operation::destroy, &m_storage, nullptr);
799  }
800 }
801 
802 //-----------------------------------------------------------------------------
803 // Observers
804 //-----------------------------------------------------------------------------
805 
806 inline BPSTD_INLINE_VISIBILITY
808  const noexcept
809 {
810  return m_storage_handler != nullptr;
811 }
812 
813 inline BPSTD_INLINE_VISIBILITY
814 const std::type_info& bpstd::any::type()
815  const noexcept
816 {
817  if (has_value()) {
818  auto* p = m_storage_handler(operation::type, nullptr, nullptr);
819  return (*static_cast<const std::type_info*>(p));
820  }
821  return typeid(void);
822 }
823 
824 //=============================================================================
825 // definition : non-member functions : class : any
826 //=============================================================================
827 
828 //-----------------------------------------------------------------------------
829 // utilities
830 //-----------------------------------------------------------------------------
831 
832 inline BPSTD_INLINE_VISIBILITY
833 void bpstd::swap(any& lhs, any& rhs)
834  noexcept
835 {
836  lhs.swap(rhs);
837 }
838 
839 //-----------------------------------------------------------------------------
840 // casts
841 //-----------------------------------------------------------------------------
842 
843 template<typename T>
844 inline BPSTD_INLINE_VISIBILITY
845 T bpstd::any_cast(any& operand)
846 {
847  using underlying_type = remove_cvref_t<T>;
848 
849  static_assert(
850  is_constructible<T, underlying_type&>::value,
851  "A program is ill-formed if T is not constructible from U&"
852  );
853 
854  auto* p = any_cast<underlying_type>(&operand);
855  if (p == nullptr) {
856  throw bad_any_cast{};
857  }
858  return static_cast<T>(*p);
859 }
860 
861 template<typename T>
862 inline BPSTD_INLINE_VISIBILITY
863 T bpstd::any_cast(any&& operand)
864 {
865  using underlying_type = remove_cvref_t<T>;
866 
867  static_assert(
868  is_constructible<T, underlying_type>::value,
869  "A program is ill-formed if T is not constructible from U"
870  );
871 
872  auto* p = any_cast<underlying_type>(&operand);
873  if (p == nullptr) {
874  throw bad_any_cast{};
875  }
876  return static_cast<T>(bpstd::move(*p));
877 }
878 
879 template<typename T>
880 inline BPSTD_INLINE_VISIBILITY
881 T bpstd::any_cast(const any& operand)
882 {
883  using underlying_type = remove_cvref_t<T>;
884 
885  static_assert(
886  is_constructible<T, const underlying_type&>::value,
887  "A program is ill-formed if T is not constructible from const U&"
888  );
889 
890  const auto* p = any_cast<underlying_type>(&operand);
891  if (p == nullptr) {
892  throw bad_any_cast{};
893  }
894  return static_cast<T>(*p);
895 }
896 
897 template<typename T>
898 inline BPSTD_INLINE_VISIBILITY
899 T* bpstd::any_cast(any* operand)
900  noexcept
901 {
902  if (!operand) {
903  return nullptr;
904  }
905  if (operand->type() != typeid(T)) {
906  return nullptr;
907  }
908 
909  auto p = operand->m_storage_handler(any::operation::value,
910  &operand->m_storage,
911  nullptr);
912  return const_cast<T*>(static_cast<const T*>(p));
913 }
914 
915 template<typename T>
916 inline BPSTD_INLINE_VISIBILITY
917 const T* bpstd::any_cast(const any* operand)
918  noexcept
919 {
920  if (!operand) {
921  return nullptr;
922  }
923  if (operand->type() != typeid(T)) {
924  return nullptr;
925  }
926 
927  auto* p = operand->m_storage_handler(any::operation::value,
928  &operand->m_storage,
929  nullptr);
930  return static_cast<const T*>(p);
931 }
932 
933 BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
934 
935 #endif /* BPSTD_ANY_HPP */
bpstd::any_cast
T any_cast(any &operand)
Attempts to cast an any back to the underlying type T.
type_traits.hpp
This header provides definitions from the C++ header <type_traits>
bpstd::any::type
const std::type_info & type() const noexcept
Gets the type_info for the underlying stored type, or typeid(void) if has_value() returns false.
Definition: any.hpp:814
bpstd::aligned_storage
Definition: type_traits.hpp:778
bpstd::any
An object that can hold values of any type via type-erasure.
Definition: any.hpp:84
bpstd::any::swap
void swap(any &other) noexcept
Swaps the contents of this with other.
Definition: any.hpp:761
bpstd::swap
void swap(any &lhs, any &rhs) noexcept
Swaps the contents of lhs and rhs.
Definition: any.hpp:833
bpstd::in_place_type_t
This function is a special disambiguation tag for variadic functions, used in any and optional.
Definition: utility.hpp:71
bpstd::any::reset
void reset() noexcept
Destroys the underlying stored value, leaving this any empty.
Definition: any.hpp:751
bpstd::any::has_value
bool has_value() const noexcept
Checks whether this any contains a value.
Definition: any.hpp:807
bpstd::swap
void swap(variant< Types... > &lhs, variant< Types... > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Swaps the contents of lhs with rhs.
bpstd::any::emplace
decay_t< ValueType > & emplace(Args &&...args)
Emplaces a ValueType into this any, destroying the previous value if it contained one.
bpstd::bad_any_cast
Definition: any.hpp:56
bpstd::any::any_cast
friend T * any_cast(any *) noexcept
Attempts to cast an any back to the underlying type T.
bpstd::any::any
any() noexcept
Constructs an any instance that does not contain any value.
Definition: any.hpp:583
bpstd::any_cast
const T * any_cast(const any *operand) noexcept
Attempts to cast an any back to the underlying type T.
bpstd::any::operator=
any & operator=(any &&other) noexcept
Assigns the contents of other to this any.
Definition: any.hpp:669
utility.hpp
This header provides definitions from the C++ header <utility>