try_cast.hpp 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. // Copyright 2019 Hans Dembinski
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_HISTOGRAM_DETAIL_TRY_CAST_HPP
  7. #define BOOST_HISTOGRAM_DETAIL_TRY_CAST_HPP
  8. #include <boost/config.hpp> // BOOST_NORETURN
  9. #include <boost/throw_exception.hpp>
  10. #include <type_traits>
  11. namespace boost {
  12. namespace histogram {
  13. namespace detail {
  14. template <class T, class U>
  15. constexpr T* ptr_cast(U*) noexcept {
  16. return nullptr;
  17. }
  18. template <class T>
  19. constexpr T* ptr_cast(T* p) noexcept {
  20. return p;
  21. }
  22. template <class T>
  23. constexpr const T* ptr_cast(const T* p) noexcept {
  24. return p;
  25. }
  26. template <class T, class E, class U>
  27. BOOST_NORETURN T try_cast_impl(std::false_type, std::false_type, U&&) {
  28. BOOST_THROW_EXCEPTION(E("type cast error"));
  29. }
  30. // converting cast
  31. template <class T, class E, class U>
  32. T try_cast_impl(std::false_type, std::true_type, U&& u) noexcept {
  33. return static_cast<T>(u); // cast to avoid warnings
  34. }
  35. // pass-through cast
  36. template <class T, class E>
  37. T&& try_cast_impl(std::true_type, std::true_type, T&& t) noexcept {
  38. return std::forward<T>(t);
  39. }
  40. // cast fails at runtime with exception E instead of compile-time, T must be a value
  41. template <class T, class E, class U>
  42. T try_cast(U&& u) noexcept(std::is_convertible<U, T>::value) {
  43. return try_cast_impl<T, E>(std::is_same<U, T>{}, std::is_convertible<U, T>{},
  44. std::forward<U>(u));
  45. }
  46. } // namespace detail
  47. } // namespace histogram
  48. } // namespace boost
  49. #endif