C ++: почему не работает мой вызов std :: uninitialized_copy? - PullRequest
2 голосов
/ 02 февраля 2011

Я строю простой класс, который должен имитировать функциональность класса std :: string (в качестве упражнения!):

#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;
};

Во избежание накладных расходов, связанных с «новым» (и чтобы увеличить мое знакомство с заголовком <memory>), я решил использовать класс шаблона библиотеки для выделения памяти для моей строки.Вот пример моего использования его в конструкторе копирования:

#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);


}

Компилятор продолжает сообщать мне две ошибки в строке "uninitialized_copy", которые оба приводят к заголовкам в библиотеке:

error: invalid conversion from 'char' to 'char*'

error: no match for 'operator!=' in '__first != __last'

Проблема в том, что я не понимаю, где в этой строке происходит преобразование из char в char *, и почему два указателя одного типа (str.first, str.onePastLast) нельзя сравнивать с "! = ".

Я мог бы использовать" new ", но, как уже было сказано, я хочу попрактиковаться с <memory>.Так может кто-нибудь сказать мне, почему это не работает?

1 Ответ

5 голосов
/ 02 февраля 2011

Глядя на стандарт raw_storage_iterator, для typedef value_type значение не равно T, но вместо этого void:

template <class OutputIterator, class T>
class raw_storage_iterator
: public iterator<output_iterator_tag,void,void,void,void>
                                      ^^^^

, тогда как uninitialized_copy должен использовать этот typedef:

template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
ForwardIterator result);

Эффекты:

for (; first != last; ++result, ++first)
::new (static_cast<void*>(&*result))
typename iterator_traits<ForwardIterator>::value_type(*first);
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

В вашем коде после всех подстановок это приводит к:

new (...&*result) void (*first);
                  ^^^^^^^^^^^^^
                 invalid use here

Из этого вы можете сделать вывод, что эти два значения никогда не предназначалисьработать вместе.

Если вы хотите использовать raw_storage_iterator, тогда должно быть хорошо передать его на std::copy, поскольку вся магия происходит при перегрузке operator=(const T&).

Есливы думаете, что все это необходимо для примитива типа char, где вы можете просто выделить с помощью new char[x] (NB! завершение NUL) и скопировать с помощью strcpy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...