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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
#include <iostream>
#include <cstring>
#include <iomanip>
namespace shallow {
struct toy_string {
static constexpr std::size_t N = 5 ;
char* pstr = new char[N] { 'a', 'b', 'c', 'd', '\0' } ;
void change( const char* cstr ) noexcept { std::strncpy( pstr, cstr, N-1 ) ; }
void dump( const char* name = "" ) const {
std::cout << "toy_string (shallow) " << name << " @ " << this << " pstr: "
<< (const void*) pstr << " => " << std::quoted(pstr) << '\n' ;
}
};
// true if a and b have the same logical state
bool operator== ( const toy_string& a, const toy_string& b )
{ return std::strcmp( a.pstr, b.pstr ) == 0 ; }
bool operator!= ( const toy_string& a, const toy_string& b ) { return !(a==b) ; }
}
namespace deep {
struct toy_string {
static constexpr std::size_t N = 5 ;
char* pstr = new char[N] { 'a', 'b', 'c', 'd', '\0' } ;
toy_string() = default ;
toy_string( const toy_string& that ) : pstr( new char[N]{} ) { change(that.pstr) ; }
toy_string( toy_string&& that ) noexcept : pstr(nullptr) { swap(that) ; }
toy_string& operator= ( toy_string that ) noexcept { swap(that) ; return *this ; }
~toy_string() { delete[] pstr ; }
void swap( toy_string& that ) noexcept { using std::swap ; swap( pstr, that.pstr) ; }
void change( const char* cstr ) noexcept { std::strncpy( pstr, cstr, N-1 ) ; }
void dump( const char* name = "" ) const {
std::cout << "toy_string (deep) " << name << " @ " << this << " pstr: "
<< (const void*) pstr << " => " << std::quoted(pstr) << '\n' ;
}
};
// true if a and b have the same logical state
bool operator== ( const toy_string& a, const toy_string& b )
{ return std::strcmp( a.pstr, b.pstr ) == 0 ; }
bool operator!= ( const toy_string& a, const toy_string& b ) { return !(a==b) ; }
}
#define DUMP(desc,x) { std::cout << std::setw(25) << desc << ": " ; (x).dump(#x) ; }
#define CHECK_EQUAL(a,b) ( std::cout << " " #a " == " #b " ? " << std::boolalpha << (a==b) << "\n\n" )
template < typename T > void test() {
const T const_aaa{} ;
DUMP( "init", const_aaa ) ;
T mutable_b = const_aaa ;
DUMP( "copy construct", mutable_b ) ;
CHECK_EQUAL( const_aaa, mutable_b ) ;
mutable_b.change("**") ;
DUMP( "after change mutable_b", mutable_b ) ;
DUMP( "after change mutable_b", const_aaa ) ;
CHECK_EQUAL( const_aaa, mutable_b ) ;
const T const_ccc{} ;
DUMP( "init", const_ccc ) ;
mutable_b = const_ccc ;
DUMP( "after assignment", mutable_b ) ;
CHECK_EQUAL( const_ccc, mutable_b ) ;
mutable_b.change("!!!") ;
DUMP( "after change mutable_b", mutable_b ) ;
DUMP( "after change mutable_b", const_ccc ) ;
CHECK_EQUAL( const_ccc, mutable_b ) ;
}
int main() {
std::cout << "shallow\n---------\n" ;
test<shallow::toy_string>() ;
std::cout << "\ndeep\n---------\n" ;
test<deep::toy_string>() ;
}
|