1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
#include <iostream>
#include <memory>
#include <cstring>
#include <algorithm>
class String final
{
public:
String() { ptr[sz] = 0 ; }
// note: member sz must be declared before ptr
String( const char* p ) : sz( std::strlen(p) ) { std::copy( p, p+sz+1, ptr.get() ) ; }
String( const String& that ) : sz(that.sz) { std::copy( that.to_cstr(), that.to_cstr()+sz+1, ptr.get() ) ; }
String( String&& that ) noexcept { swap(that) ; } // move constructor
// String(char *p); // not required
// unifying assignment operator:
// https://en.wikibooks.org/wiki/More_C++_Idioms/Copy-and-swap
String& operator = ( String rhs ) noexcept { return swap(rhs) ; }
~String() = default ;
String& operator += ( const String& rhs )
{
auto tmp = std::make_unique< char[] >( sz + rhs.sz + 1 ) ;
std::copy( begin(), end(), tmp.get() ) ;
std::copy( rhs.to_cstr(), rhs.to_cstr()+rhs.sz+1, tmp.get()+sz ) ;
sz += rhs.sz ;
using std::swap ; swap( ptr, tmp ) ;
return *this ;
}
unsigned long length() const noexcept { return sz ; }
const char* to_cstr() const noexcept { return ptr.get() ; }
// right now: just to support range-based loops
char* begin() noexcept { return ptr.get() ; }
char* end() noexcept { return begin() + length() ; }
const char* begin() const noexcept { return to_cstr() ; }
const char* end() const noexcept { return begin() + length() ; }
String& swap( String& that ) noexcept
{
using std::swap ;
swap( sz, that.sz ) ;
swap( ptr, that.ptr ) ;
return *this ;
}
private:
// note: member sz must be declared before ptr
std::size_t sz = 0 ;
std::unique_ptr< char[] > ptr = std::make_unique< char[] >(sz+1) ;
friend std::ostream& operator <<( std::ostream &out, const String& str )
{ for( char c : str ) out << c ; return out ; }
// canonical: see 'Binary arithmetic operators' in
// http://en.cppreference.com/w/cpp/language/operators
friend String operator + ( String lhs, const String& rhs ) { return lhs += rhs ; }
friend String operator + ( String lhs, const char* p ) { return lhs += p ; }
friend String operator + ( const char* p, const String& rhs )
{ return String(p) += rhs ; } // not the most efficient way of implementing this
};
void swap( String& a, String& b ) { a.swap(b) ; }
int main()
{
const String s5 = "hi there i am ki.";
const String s6 = "message: " + s5 + " sea grundy" ;
String s7 ;
s7 += "Just Testing!" ;
std::cout << s6 << '\n' << s7 << '\n' ;
for( char& c : s7 ) c = std::toupper(c) ;
std::cout << s7 << '\n' ;
}
|