#pragma once #include #include namespace c10 { template TypePtr getTypePtr(); std::string toString(TypePtr typePtr); template List::List(c10::intrusive_ptr>&& elements) : impl_(std::move(elements)) {} template List::List() : List(make_intrusive::StorageT>>( typename detail::ListImpl::StorageT>::list_type(), getTypePtr())) { static_assert(!std::is_same::value, "This constructor is not valid for List. Please use c10::impl::GenericList(elementType) instead."); } template List::List(ArrayRef values) : List(make_intrusive::StorageT>>( typename detail::ListImpl::StorageT>::list_type(), getTypePtr())) { static_assert(!std::is_same::value, "This constructor is not valid for List. Please use c10::impl::GenericList(elementType)."); impl_->list.reserve(values.size()); for (const T& element : values) { impl_->list.push_back(element); } } template List::List(std::initializer_list initial_values) : List(ArrayRef(initial_values)) { static_assert(!std::is_same::value, "This constructor is not valid for List. Please use c10::impl::GenericList(elementType)."); } template List::List(TypePtr elementType) : List(make_intrusive>( typename detail::ListImpl::list_type(), std::move(elementType))) { static_assert(std::is_same::value, "This constructor is only valid for c10::impl::GenericList."); } namespace impl { template List toTypedList(impl::GenericList list) { static_assert(std::is_same::StorageT>::value, "Can only call toTypedList with lists that store their elements as IValues."); TORCH_INTERNAL_ASSERT(*getTypePtr() == *list.impl_->elementType, "Tried to cast a List<", toString(list.impl_->elementType), "> to a List<", toString(getTypePtr()), ">. Types mismatch."); return List(std::move(list.impl_)); } template impl::GenericList toGenericList(List list) { static_assert(std::is_same::StorageT>::value, "Can only call toGenericList with lists that store their elements as IValues."); return GenericList(std::move(list.impl_)); } } template List::List(List&& rhs) noexcept: impl_(std::move(rhs.impl_)) { rhs.impl_ = make_intrusive>(std::vector{}, impl_->elementType); } template List& List::operator=(List&& rhs) noexcept { impl_ = std::move(rhs.impl_); rhs.impl_ = make_intrusive>(std::vector{}, impl_->elementType); return *this; } template List List::copy() const { return List(impl_->copy()); } namespace detail { template T list_element_to(T element) { return element; } template T list_element_to(const IValue& element) { return element.template to(); } template T list_element_to(IValue&& element) { return std::move(element).template to(); } template StorageT list_element_from(const T& element) { return element; } template StorageT list_element_from(T&& element) { return std::move(element); } } namespace impl { template ListElementReference::operator T() const { return detail::list_element_to(*iterator_); } template ListElementReference& ListElementReference::operator=(T&& new_value) && { *iterator_ = detail::list_element_from(std::move(new_value)); return *this; } template ListElementReference& ListElementReference::operator=(const T& new_value) && { *iterator_ = detail::list_element_from(std::move(new_value)); return *this; } template ListElementReference& ListElementReference::operator=(ListElementReference&& rhs) && { *iterator_ = *rhs.iterator_; return *this; } template void swap(ListElementReference&& lhs, ListElementReference&& rhs) { std::swap(*lhs.iterator_, *rhs.iterator_); } } template void List::set(size_type pos, const value_type& value) const { impl_->list.at(pos) = detail::list_element_from(value); } template void List::set(size_type pos, value_type&& value) const { impl_->list.at(pos) = detail::list_element_from(std::move(value)); } template typename List::value_type List::get(size_type pos) const { return detail::list_element_to(impl_->list.at(pos)); } template typename List::internal_reference_type List::operator[](size_type pos) const { static_cast(impl_->list.at(pos)); // Throw the exception if it is out of range. return {impl_->list.begin() + pos}; } template typename List::value_type List::extract(size_type pos) const { auto& elem = impl_->list.at(pos); auto result = detail::list_element_to(std::move(elem)); if (std::is_same::value) { // Reset the list element to a T() instead of None to keep it correctly typed elem = detail::list_element_from(T{}); } return result; } template typename List::iterator List::begin() const { return iterator(impl_->list.begin()); } template typename List::iterator List::end() const { return iterator(impl_->list.end()); } template bool List::empty() const { return impl_->list.empty(); } template typename List::size_type List::size() const { return impl_->list.size(); } template void List::reserve(size_type new_cap) const { impl_->list.reserve(new_cap); } template void List::clear() const { impl_->list.clear(); } template typename List::iterator List::insert(iterator pos, const T& value) const { return iterator { impl_->list.insert(pos.iterator_, detail::list_element_from(value)) }; } template typename List::iterator List::insert(iterator pos, T&& value) const { return iterator { impl_->list.insert(pos.iterator_, detail::list_element_from(std::move(value))) }; } template template typename List::iterator List::emplace(iterator pos, Args&&... value) const { // TODO Use list_element_from? return iterator { impl_->list.emplace(pos.iterator_, std::forward(value)...) }; } template void List::push_back(const T& value) const { impl_->list.push_back(detail::list_element_from(value)); } template void List::push_back(T&& value) const { impl_->list.push_back(detail::list_element_from(std::move(value))); } template void List::append(List b) const { if (b.use_count() == 1) { impl_->list.insert(impl_->list.end(), make_move_iterator(b.impl_->list.begin()), make_move_iterator(b.impl_->list.end())); } else { impl_->list.insert(impl_->list.end(), b.impl_->list.begin(), b.impl_->list.end()); } } template template void List::emplace_back(Args&&... args) const { // TODO Use list_element_from? impl_->list.emplace_back(std::forward(args)...); } template typename List::iterator List::erase(iterator pos) const { return iterator { impl_->list.erase(pos.iterator_) }; } template typename List::iterator List::erase(iterator first, iterator last) const { return iterator { impl_->list.erase(first.iterator_, last.iterator_) }; } template void List::pop_back() const { impl_->list.pop_back(); } template void List::resize(size_type count) const { impl_->list.resize(count, T{}); } template void List::resize(size_type count, const T& value) const { impl_->list.resize(count, value); } template bool list_is_equal(const List& lhs, const List& rhs) { if (lhs.size() != rhs.size()) { return false; } for (size_t i = 0; i < lhs.size(); ++i) { if (lhs.get(i) != rhs.get(i)) { return false; } } return true; } template size_t List::use_count() const { return impl_.use_count(); } template TypePtr List::elementType() const { return impl_->elementType; } template void List::unsafeSetElementType(TypePtr t) { impl_->elementType = std::move(t); } }