2016-10-03 7 views
0

Так я использую пользовательский вектор контейнер из: https://github.com/patr0nus/Vector/blob/master/Vector.hПользовательские вектор не поддерживает unique_ptr

, и я пытаюсь создать вектор Пойнтинга unique_ptr к объекту пользовательского класса.

Раньше завершаться:

error: object of type 'std::__1::unique_ptr std::__1::default_delete>' cannot be assigned because its copy assignment operator is implicitly deleted

Я установил его, добавив следующий код vector.h:

void push_back(T&& val) 
    { 
     resize(m_size + 1); 
     m_container[m_size - 1] = std::move(val); 
    } 

Теперь проблема, я не могу перебрать этот вектор и другие функции, такие как swap терпят неудачу:

no matching function for call to 'swap' 
     swap(*__x4, *__x5); 
candidate template ignored: could not match 'tuple' against 'unique_ptr' 
swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u) 

мне нужно некоторое руководство о том, как исправить тыс проблемы.

+0

Этот вектор, кажется, предназначен для использования с POD. –

+9

Использование 'std :: vector' является решением проблемы. Зачем вам этот заказ в первую очередь? Проблема с реализацией заключается в том, что она абсолютно требует, чтобы 'T' был CopyConstructible, когда' std :: unique_ptr' очень не является. – AndyG

+3

Ум ..... Почему бы просто не использовать std :: vector? – mascoj

ответ

5

Вы не можете использовать patr0nus/Vector с не-POD-типами. Причина довольно проста: во многих местах она использует memcpy и требует, чтобы типы были скопированы.

Использование его с чем-либо еще, что не является POD, на самом деле является неопределенным поведением. Не используйте этот вектор для типов не POD. Об этом нет.

Как вы знаете, вы можете использовать четко определенную реализацию, которая учитывает точный набор требований и, вероятно, более оптимизирована, чем эта векторная реализация: std::vector.

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

1

Чтобы добавить к ответу, так как ваш векторный класс работает только с типами POD, то вы можете гарантировать, что работаете с типами POD только, чтобы использовать функцию std::is_pod вместе с static_assert. Использование этих средств на C++ запретит создание программ, которые нарушают требования POD.

Когда вы строите вектор, вы можете сделать тесты в этих функциях:

#include <algorithm> 
//... 
template<typename T> 
class Vector 
{ 
    Vector(int initialSize = 1) 
    { 
     static_assert(std::is_pod<T>(), "Sorry, only POD types are allowed"); 
    //... 
    } 

    Vector(const Vector &source) 
    { 
     static_assert(std::is_pod<T>(), "Sorry, only POD types are allowed"); 
     //... 
    } 
    //... 
}; 

Это гарантирует, что если кто-нибудь сделать что-то вроде этого:

Vector<std::string> sV; 

ошибка компиляции покажет вместо компиляции кода и возникновения проблем, которые вы видите сейчас.

+0

'is_pod' конвертируется в bool, поэтому просто' static_assert (std :: is_pod {}, "blah") 'подходит. Кроме того, вы можете утверждать это один раз в верхней части класса. :) – GManNickG

0

В изменении размера() функции вы имеете:

{ 
... 
      m_capacity = size * 2;//The new capacity is double of the size. 
      T* oldPtr = m_container; 
      m_container = (T*)malloc(m_capacity * sizeof(T));//Allocate the new container. 
      memcpy(m_container, oldPtr, m_size * sizeof(T));//Copy the elements. 
      destory(oldPtr, m_size);//Destory the old container. 
      free(oldPtr); 
... 
} 

Таким образом, вы должны поставить POD (простые старые данные) элементов вам вектор:
What are POD types in C++?