Advertisement
zhangsongcui

Immutable String

Nov 16th, 2011
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.65 KB | None | 0 0
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <type_traits>
  4. #include <memory>
  5. #include <cassert>
  6.  
  7. enum class Place {inInitializedReadonlyArea, inHeapArea};
  8.  
  9. template <typename Type, Place Where>
  10. class ImmutableString;
  11.  
  12. template <typename Type>
  13. class ImmutableString<Type, Place::inInitializedReadonlyArea>
  14. {
  15.     static_assert(std::is_same<Type, char>::value || std::is_same<Type, wchar_t>::value, "The type you've given is currently unsupported");
  16.  
  17. public: // Should be privated, bug because of an error...
  18.     ImmutableString(const Type* const str_, const size_t len_): str(str_), len(len_) {}
  19.  
  20. private:
  21.     ImmutableString() = delete;
  22.     void operator delete(void *) = delete;
  23.     void* operator new(size_t) = delete;
  24.  
  25. public:
  26.     size_t getLength() const
  27.     {
  28.         return len;
  29.     }
  30.  
  31.     Type operator [](size_t index) const
  32.     {
  33.         assert(index < len);
  34.         return str[index];
  35.     }
  36.  
  37.     ImmutableString<Type, Place::inInitializedReadonlyArea> substr(size_t pos = 0, size_t n = npos) const
  38.     {
  39.         assert(pos < len);
  40.         ImmutableString<Type, Place::inInitializedReadonlyArea> result(*this);
  41.         result.str += pos;
  42.         result.len = (n > len || n + pos > len) ? len - pos : n;
  43.         return result;
  44.     }
  45.  
  46.     friend std::basic_ostream<Type>& operator <<(std::basic_ostream<Type>& os, const ImmutableString<Type, Place::inInitializedReadonlyArea>& rhs)
  47.     {
  48.         std::copy_n(rhs.str, rhs.len, std::ostreambuf_iterator<Type>(os));
  49.         return os;
  50.     }
  51.  
  52.     //invalid argument list; is it a bug of g++ 4.7?
  53.     //friend ImmutableString<char, Place::Instack> operator "" _ImmStr(const char*, size_t);
  54.  
  55.     template <typename T, Place W> friend
  56.     ImmutableString<T, Place::inHeapArea> operator +(const ImmutableString<T, W>& str1, const ImmutableString<T, W>& str2);
  57.  
  58. public:
  59.     static const size_t npos = size_t(-1);
  60.  
  61. private:
  62.     const Type* str;
  63.     size_t len;
  64. };
  65.  
  66. ImmutableString<char, Place::inInitializedReadonlyArea> operator "" _ImmStr(const char* str_, size_t len_)
  67. {
  68.     return ImmutableString<char, Place::inInitializedReadonlyArea>(str_, len_);
  69. }
  70.  
  71. ImmutableString<wchar_t, Place::inInitializedReadonlyArea> operator "" _ImmStr(const wchar_t* str_, size_t len_)
  72. {
  73.     return ImmutableString<wchar_t, Place::inInitializedReadonlyArea>(str_, len_);
  74. }
  75.  
  76. template <typename Type>
  77. class ImmutableString<Type, Place::inHeapArea>
  78. {
  79.     static_assert(std::is_same<Type, char>::value || std::is_same<Type, wchar_t>::value, "The type you've given is currently unsupported");
  80.  
  81. private:
  82.     ImmutableString() = delete;
  83.     ImmutableString(const size_t len_): srcStr(new Type[len_], [](Type* str){ delete[] str; }), str(srcStr.get()), len(len_) {}
  84.     void operator delete(void *) = delete;
  85.     void* operator new(size_t) = delete;
  86.  
  87. public:
  88.     size_t getLength() const
  89.     {
  90.         return len;
  91.     }
  92.  
  93.     Type operator [](size_t index) const
  94.     {
  95.         assert(index < len);
  96.         return str[index];
  97.     }
  98.  
  99.     friend std::basic_ostream<Type>& operator <<(std::basic_ostream<Type>& os, const ImmutableString<Type, Place::inHeapArea>& rhs)
  100.     {
  101.         std::copy_n(rhs.str, rhs.len, std::ostreambuf_iterator<Type>(os));
  102.         return os;
  103.     }
  104.  
  105.     ImmutableString substr(size_t pos = 0, size_t n = npos) const
  106.     {
  107.         assert(pos < len);
  108.         ImmutableString result(*this);
  109.         result.str += pos;
  110.         result.len = (n > len || n + pos > len) ? len - pos : n;
  111.         return result;
  112.     }
  113.  
  114.     template <typename T, Place W> friend
  115.     ImmutableString<T, Place::inHeapArea> operator +(const ImmutableString<T, W>& str1, const ImmutableString<T, W>& str2);
  116.  
  117. public:
  118.     static const size_t npos = size_t(-1);
  119.  
  120. private:
  121.     std::shared_ptr<Type> srcStr;
  122.     Type* str;
  123.     size_t len;
  124. };
  125.  
  126. template <typename Type, Place Where>
  127. ImmutableString<Type, Place::inHeapArea> operator +(const ImmutableString<Type, Where>& str1, const ImmutableString<Type, Where>& str2)
  128. {
  129.     ImmutableString<Type, Place::inHeapArea> result(str1.len + str2.len);
  130.     std::copy_n(&str1.str[0], str1.len, &result.str[0]);
  131.     std::copy_n(&str2.str[0], str2.len, &result.str[str1.len]);
  132.     return result;
  133. }
  134.  
  135. int main()
  136. {
  137.     using namespace std;
  138.     cout << "1234567"_ImmStr.substr(3) << endl;         // Don't need to allocate heap memory
  139.     cout << std::string("1234567").substr(3) << endl;   // May allocate heap memory twice;
  140.     cout << ("1234567"_ImmStr + "abcdefg"_ImmStr).substr(3, 7) << endl;         // Only allocate heap memory once (or twice >_<)
  141.     cout << (std::string("1234567") += "abcdefg").substr(3, 7) << endl;         // May allocate heap memory 3 times
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement