any_string.hpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. //
  2. // Copyright (c) 2023 Alexander Grund
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. #ifndef BOOST_LOCALE_DETAIL_ANY_STRING_HPP_INCLUDED
  7. #define BOOST_LOCALE_DETAIL_ANY_STRING_HPP_INCLUDED
  8. #include <boost/locale/config.hpp>
  9. #include <boost/assert.hpp>
  10. #include <boost/utility/string_view.hpp>
  11. #include <memory>
  12. #include <stdexcept>
  13. #include <string>
  14. /// \cond INTERNAL
  15. namespace boost { namespace locale { namespace detail {
  16. /// Type-erased std::basic_string
  17. class any_string {
  18. struct BOOST_SYMBOL_VISIBLE base {
  19. virtual ~base() = default;
  20. virtual base* clone() const = 0;
  21. protected:
  22. base() = default;
  23. base(const base&) = default;
  24. base(base&&) = delete;
  25. base& operator=(const base&) = default;
  26. base& operator=(base&&) = delete;
  27. };
  28. template<typename Char>
  29. struct BOOST_SYMBOL_VISIBLE impl : base {
  30. explicit impl(const boost::basic_string_view<Char> value) : s(value) {}
  31. impl* clone() const override { return new impl(*this); }
  32. std::basic_string<Char> s;
  33. };
  34. std::unique_ptr<const base> s_;
  35. public:
  36. any_string() = default;
  37. any_string(const any_string& other) : s_(other.s_ ? other.s_->clone() : nullptr) {}
  38. any_string(any_string&&) = default;
  39. any_string& operator=(any_string other) // Covers the copy and move assignment
  40. {
  41. s_.swap(other.s_);
  42. return *this;
  43. }
  44. template<typename Char>
  45. void set(const boost::basic_string_view<Char> s)
  46. {
  47. BOOST_ASSERT(!s.empty());
  48. s_.reset(new impl<Char>(s));
  49. }
  50. template<typename Char>
  51. std::basic_string<Char> get() const
  52. {
  53. if(!s_)
  54. throw std::bad_cast();
  55. return dynamic_cast<const impl<Char>&>(*s_).s;
  56. }
  57. };
  58. }}} // namespace boost::locale::detail
  59. /// \endcond
  60. #endif