There are tons of problems with your code, so let's do this step by step.
First, you don't need your preprocessor magic for the namespace, but just a basic namespace mynamespace{}.
Secondly, it is ideal to create a basic_string class, so that it can be used with different character types. char / wchar_t, e.t.c.
Problems with your class:
1) private: const char *_str;. The pointer will be modified, so the const is useless.
2) There are no typedefs. You need them if you are attempting to re-implement a STL class. (Explained in example)
3) Use an allocator. This way you can construct, and destroy elements, allocate, and deallocate memory. You will be certain to keep your memory a lot safer this way.
4) Strings must be null terminated. That means an extra '\0' at the end, meaning you will have to allocate an extra byte for that. Strings are null terminated, because it is a way of telling the code to stop reading the string.
5) You are assigning to a string which has not been allocated. _str = s.c_str(); could easily crash, depending on your compiler, because you are writing to non-allocated memory.
6) Use const references, rather than normal types for your parameters (string = const string &). You also need this for your copy constructor basic_string(const _Myt &).
I still may not have highlighted all of the problems
Example basic_string class
template < typename _Elem, typename _Traits = std::char_traits<_Elem>, typename _Alloc = std::allocator<_Elem> > class basic_string
{
public:
typedef basic_string<_Elem, _Traits, _Alloc> _Myt;
typedef _Elem value_type;
typedef _Traits traits_type;
typedef _Alloc allocator_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef value_type *iterator;
typedef const value_type *const_iterator;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
basic_string()
{
__data = _Alloc().allocate(1);
_Alloc().construct(&__data[0], '\0');
}
basic_string(const_pointer _Init)
{
int count = 0;
__data = _Alloc().allocate(_Traits::length(_Init) + 1);
for (const_iterator i = &_Init[0]; i != &_Init[_Traits::length(_Init)]; ++i, ++count)
{
_Alloc().construct(&__data[count], *i);
}
_Alloc().construct(&__data[_Traits::length(_Init)], '\0');
}
basic_string(const _Myt &_Init)
{
if (this != &_Init)
{
int count = 0;
__data = _Alloc().allocate(_Traits::length(_Init.__data) + 1);
for (const_iterator i = &_Init.__data[0]; i != &_Init.__data[_Traits::length(_Init.__data)]; ++i, ++count)
{
_Alloc().construct(&__data[count], *i);
}
_Alloc().construct(&__data[_Traits::length(_Init.__data)], '\0');
}
else
{
__data = _Alloc().allocate(1);
_Alloc().construct(&__data[0], '\0');
}
}
~basic_string()
{
if (__data)
{
size_type tmp = size();
for (iterator i = begin(); i != end(); ++i)
{
_Alloc().destroy(i);
}
_Alloc().deallocate(__data, tmp);
}
}
_Myt &assign(const_pointer _Rhs)
{
int count = 0;
reserve(_Traits::length(_Rhs) + 1);
for (const_iterator i = &_Rhs[0]; i != &_Rhs[_Traits::length(_Rhs)]; ++i, ++count)
{
_Alloc().construct(&__data[count], *i);
}
_Alloc().construct(&__data[_Traits::length(_Rhs)], '\0');
return *this;
}
_Myt &operator=(const_pointer _Rhs)
{
return assign(_Rhs);
}
_Myt &append(const_pointer _Rhs)
{
int count = size();
reserve(size() + _Traits::length(_Rhs) + 1);
for (const_iterator i = &_Rhs[0]; i != &_Rhs[_Traits::length(_Rhs)]; ++i, ++count)
{
_Alloc().construct(&__data[count], *i);
}
_Alloc().construct(&__data[count], '\0');
return *this;
}
_Myt &operator+=(const_pointer _Rhs)
{
return append(_Rhs);
}
iterator begin()
{
return &__data[0];
}
iterator end()
{
return &__data[size()];
}
size_type size()
{
return _Traits::length(__data);
}
_Myt &swap(basic_string<_Elem> &_Rhs)
{
std::swap(__data, _Rhs.__data);
return *this;
}
void reserve(size_type _Size)
{
int count = 0;
if (_Size < size())
{
return;
}
pointer buf = _Alloc().allocate(_Size);
for (iterator i = begin(); i != end(); ++i, ++count)
{
_Alloc().construct(&buf[count], *i);
}
std::swap(__data, buf);
for (iterator i = &buf[0]; i != &buf[_Traits::length(buf)]; ++i)
{
_Alloc().destroy(i);
}
_Alloc().deallocate(buf, _Traits::length(buf));
}
operator const_pointer()
{
return __data;
}
operator pointer()
{
return __data;
}
template < typename _Traits1, typename _Alloc1 > friend std::basic_ostream<_Elem> &operator<<(std::basic_ostream<_Elem> &_Stream, basic_string<_Elem, _Traits1, _Alloc1> &_Str)
{
return _Stream << _Str.c_str();
}
const_pointer data() const
{
return __data;
}
const_pointer c_str() const
{
return __data;
}
private:
pointer __data;
};
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
Of course, there is still a bit missing, but I'm sure you can implement that with a little online help.
stringconflicts withstd::string. Of course you could haveyournamespace::string, but it's better to avoid the confusion altogether.using namespace std;anyway.#definepreprocessor magic and just put the namespace scope inline.