fork download
  1. #include <iostream> // std::cout, std::boolalpha, std::endl
  2. #include <string> // std::basic_string
  3. #include <type_traits> // std::enable_if_t, std::is_same
  4. #include <utility> // std::swap, std::move
  5.  
  6. namespace danger_zone // enter at your own peril
  7. {
  8. template<typename CharT>
  9. struct nullable_basic_string : public std::basic_string<CharT>
  10. {
  11. protected:
  12. using basic_string = std::basic_string<CharT>;
  13.  
  14. bool _isNull = false;
  15.  
  16. public:
  17. using basic_string::basic_string; // inherit constructors
  18.  
  19. nullable_basic_string(basic_string const &str) : basic_string{ str }
  20. {
  21. }
  22.  
  23. nullable_basic_string(decltype(nullptr)) : basic_string{}, _isNull{ true }
  24. {
  25. }
  26.  
  27. nullable_basic_string() : nullable_basic_string{ nullptr }
  28. {
  29. }
  30.  
  31. nullable_basic_string& operator=(nullable_basic_string rhs)
  32. {
  33. using std::swap;
  34. basic_string::swap(rhs);
  35. swap(_isNull, rhs._isNull);
  36. return *this;
  37. }
  38.  
  39. friend bool operator==(nullable_basic_string const &lhs, decltype(nullptr) const &rhs)
  40. {
  41. return lhs._isNull;
  42. }
  43.  
  44. friend bool operator==(decltype(nullptr) const &lhs, nullable_basic_string const &rhs)
  45. {
  46. return rhs == lhs;
  47. }
  48.  
  49. friend bool operator!=(nullable_basic_string const &lhs, decltype(nullptr) const &rhs)
  50. {
  51. return !(lhs == rhs);
  52. }
  53.  
  54. friend bool operator!=(decltype(nullptr) const &lhs, nullable_basic_string const &rhs)
  55. {
  56. return rhs != lhs;
  57. }
  58. };
  59.  
  60. using nullable_string = nullable_basic_string<char>;
  61.  
  62. ////////////////////////////////////////////////////
  63. // TODO: throw exception on null access //
  64. ////////////////////////////////////////////////////
  65.  
  66. } // namespace danger_zone
  67.  
  68. int main(int, char**) noexcept
  69. {
  70. using danger_zone::nullable_string;
  71. nullable_string ns{};
  72. nullable_string ns_copy{ ns };
  73. nullable_string tmp_copy_n{ std::move(nullable_string{}) };
  74. nullable_string tmp_copy_h{ std::move(nullable_string{ "Hello World!" }) };
  75. nullable_string hello{ "Hello World!" };
  76. nullable_string ns_assigned{};
  77. ns_assigned = "Goodbye, Galaxy!";
  78. nullable_string hello_assigned{ hello };
  79. hello_assigned = nullptr;
  80. std::cout << std::boolalpha << std::endl
  81. << "ns == nullptr? " << (ns == nullptr) << std::endl
  82. << "nullptr == ns? " << (nullptr == ns) << std::endl
  83. << "ns_copy == nullptr? " << (ns_copy == nullptr) << std::endl
  84. << "tmp_copy_n == nullptr? " << (tmp_copy_n == nullptr) << std::endl
  85. << "tmp_copy_h == nullptr? " << (tmp_copy_h == nullptr) << std::endl
  86. << "hello == nullptr? " << (hello == nullptr) << std::endl
  87. << "ns_assigned == nullptr? " << (ns_assigned == nullptr) << std::endl
  88. << "hello_assigned == nullptr? " << (hello_assigned == nullptr) << std::endl
  89. << ns_assigned << std::endl;
  90. return 0;
  91. }
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
ns == nullptr? true
nullptr == ns? true
ns_copy == nullptr? true
tmp_copy_n == nullptr? true
tmp_copy_h == nullptr? false
hello == nullptr? false
ns_assigned == nullptr? false
hello_assigned == nullptr? true
Goodbye, Galaxy!