Внешний шаблонный класс vector<unique_ptr <... >> альтернатива
Это началось с вопроса: "Почему невозможно явно создать экземпляр std::vector из std::unique_ptr?" как в:
template class std::vector<std::unique_ptr<int>>;
хотя следующие явные экземпляры и переменные хороши:
template class std::vector<int>;
template class std::unique_ptr<int>;
int main() {
std::vector<int> ints;
std::vector<std::unique_ptr<int>> pointers;
}
Но вопрос изменился на: "Какими будут альтернативы?"
Я опубликую свой краткий обзор, чтобы ответить на оба вопроса, так как я не нашел вопрос, который был достаточно похожим. Я также ищу альтернативы, если таковые имеются.
1 ответ
Почему это невозможно?
Это невозможно сделать:
template class std::vector<std::unique_ptr<int>>; // (1)
Хотя компилятор вполне подходит для такой переменной:
std::vector<std::unique_ptr<int>> vec; // (2)
Насколько я понимаю, (2) возможно, потому что методы, использующие назначения / конструкторы копирования, никогда неявно не создаются в векторе;
и (1) невозможно, потому что вектор пытается создать экземпляры методов, пытающихся сделать копии на unique_ptr.
Первый способ не скомпилировать для gcc 7.2.1 C++17, например, vector::push_back(const T&);
Поскольку T = unique_ptr, а unique_ptr, очевидно, не поддерживает операции копирования.
Какие есть альтернативы?
shared_ptr вместо unique_ptr работает, потому что поддерживает копирование, а также выглядит чисто. Но, как я слышал, у него есть некоторые накладные расходы, и мы не намерены делиться правами собственности на ресурсы.
Я также представляю, как написать оболочку, которая определяет операции "копирования", которые фактически будут перемещаться при копировании или даже выбросе, например:
template<typename T>
struct UniquePtrWithCopy {
/*mutable if move is used*/ std::unique_ptr<T> mPtr;
UniquePtrWithCopy() = default;
explicit UniquePtrWithCopy(std::unique_ptr<T>&& other)
: mPtr{std::move(other)} {
}
UniquePtrWithCopy(const UniquePtrWithCopy& other) {
mPtr = std::move(other.mPtr); // needed for operations, like resize
// or
throw std::runtime_error{"This is not intended"};
}
UniquePtrWithCopy& operator =(const UniquePtrWithCopy& other) {
if(this != &other) {
mPtr = std::move(other.mPtr);
}
return *this;
// or
throw std::runtime_error{"This is not intended"};
}
};
И тогда это возможно:
template class std::vector<UniquePtrWithMovingCopy<int>>;
Так что, думаю, хотя я и пытался найти ответ, я все-таки нашел его сам, но я был бы рад услышать некоторые другие способы или исправления.
Было бы неплохо, однако, если бы компилятор выполнил какой-то трюк sfinae и только частично создал экземпляр того, что возможно, но это, вероятно, имеет свои собственные проблемы.