C++ : Why isn't my call to "std::uninitialized_copy" working?
I building a simple class that is supposed to mimic the functionality of the std::string class (as an exercise!):
#ifndef _STR12_1_H
#define _STR12_1_H
#include <string>
#include <iostream>
class Str12_1
{
public:
typedef char* iterator;
typedef const char* const_iterator;
typedef long size_type;
Str12_1();
Str12_1(const开发者_运维问答 Str12_1& str);
Str12_1(const char *p);
Str12_1(const std::string& s);
size_type size() const;
//Other member functions
private:
iterator first;
iterator onePastLast;
iterator onePastAllocated;
};
In order to avoid the overhead associated with "new" (and to increase my familiarity with the <memory>
header), i've opted to use the library's allocator template class to allocate memory for my string. Here is an example of my use of it in the copy constructor:
#include <memory>
#include <algorithm>
using std::allocator;
using std::raw_storage_iterator;
using std::uninitialized_copy;
Str12_1::Str12_1(const Str12_1& str)
{
allocator<char> charAlloc;
first = charAlloc.allocate(str.size());
onePastLast = onePastAllocated = first + str.size();
*onePastLast = '\0';
raw_storage_iterator<char*, char> it(first);
uninitialized_copy(str.first, str.onePastLast, it);
}
The compiler keeps telling me two errors on the "uninitialized_copy" line which both lead back to headers in the library, :
error: invalid conversion from 'char' to 'char*'
error: no match for 'operator!=' in '__first != __last'
The problem is that I don't understand where on that line the conversion from char to char* is, and why two pointers of the same type (str.first, str.onePastLast) cannot be compared with "!=".
I could use "new", but as stated before, I want to get practice with <memory>
. So can someone tell me why this isn't working?
Looking at the standard raw_storage_iterator
does not typedef value_type
to be T
, but it's void
instead:
template <class OutputIterator, class T>
class raw_storage_iterator
: public iterator<output_iterator_tag,void,void,void,void>
^^^^
whereas uninitialized_copy
has to use that typedef:
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
ForwardIterator result);
Effects:
for (; first != last; ++result, ++first)
::new (static_cast<void*>(&*result))
typename iterator_traits<ForwardIterator>::value_type(*first);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In your code, after all substitutions, this leads to:
new (...&*result) void (*first);
^^^^^^^^^^^^^
invalid use here
From that you can conclude that those two were never meant to work together.
If you want to use raw_storage_iterator
, then it should be fine to pass it to std::copy
since all the magic happens in the operator=(const T&)
overload.
If you think any of this is necessary for a primitive like char
where you might just allocate with new char[x]
(NB! terminating NUL) and copy with strcpy
.
精彩评论