aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/lib
diff options
context:
space:
mode:
authorGravatar Tim Shen <timshen@google.com>2018-08-30 11:20:16 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2018-08-30 11:29:03 -0700
commit09f2c342c0e74834bebf8045d5e77dcef8323539 (patch)
tree3a969695f54840366629df7f39e4da7f9ac103cd /tensorflow/core/lib
parent9e12f1df3270b5e0b310645e6c3cae9fbd3f5dfc (diff)
Remove (Mutable)ArraySlice implementation and alias them to absl::Span.
There are several API migrations happening: * ArraySlice's sub-slice constructor => .subspan * MutableArraySlice's container pointer constructor => absl::MakeSpan PiperOrigin-RevId: 210946124
Diffstat (limited to 'tensorflow/core/lib')
-rw-r--r--tensorflow/core/lib/gtl/array_slice.h281
-rw-r--r--tensorflow/core/lib/gtl/array_slice_internal.h269
-rw-r--r--tensorflow/core/lib/gtl/array_slice_test.cc664
3 files changed, 5 insertions, 1209 deletions
diff --git a/tensorflow/core/lib/gtl/array_slice.h b/tensorflow/core/lib/gtl/array_slice.h
index b773a65569..8f47faf89e 100644
--- a/tensorflow/core/lib/gtl/array_slice.h
+++ b/tensorflow/core/lib/gtl/array_slice.h
@@ -13,293 +13,22 @@ See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
-// An ArraySlice<T> represents an immutable array of elements of type
-// T. It has a length "length", and a base pointer "ptr", and the
-// array it represents contains the elements "ptr[0] .. ptr[len-1]".
-// The backing store for the array is *not* owned by the ArraySlice
-// object, and clients must arrange for the backing store to remain
-// live while the ArraySlice object is in use.
-//
-// An ArraySlice<T> is somewhat analogous to a StringPiece, but for
-// array elements of type T.
-//
-// Implicit conversion operations are provided from types such as
-// std::vector<T> and util::gtl::InlinedVector<T, N>. Note that ArraySlice
-// objects constructed from types in this way may be invalidated by
-// any operations that mutate the underlying vector.
-//
-// One common use for ArraySlice is when passing arguments to a
-// routine where you want to be able to accept a variety of array
-// types (e.g. a vector, a util::gtl::InlinedVector, a C-style array,
-// etc.). The usual approach here is to have the client explicitly
-// pass in a pointer and a length, as in:
-//
-// void MyRoutine(const int* elems, int N) {
-// for (int i = 0; i < N; i++) { .. do something with elems[i] .. }
-// }
-//
-// Unfortunately, this leads to ugly and error-prone code at the call site:
-//
-// std::vector<int> my_vector;
-// MyRoutine(vector_as_array(&my_vector), my_vector.size());
-//
-// util::gtl::InlinedVector<int, 4> my_inline_vector;
-// MyRoutine(my_inline_vector.array(), my_inline_vector.size());
-//
-// int my_array[10];
-// MyRoutine(my_array, 10);
-//
-// Instead, you can use an ArraySlice as the argument to the routine:
-//
-// void MyRoutine(ArraySlice<int> a) {
-// for (int i = 0; i < a.size(); i++) { .. do something with a[i] .. }
-// }
-//
-// This makes the call sites cleaner, for the most part:
-//
-// std::vector<int> my_vector;
-// MyRoutine(my_vector);
-//
-// util::gtl::InlinedVector<int, 4> my_inline_vector;
-// MyRoutine(my_inline_vector);
-//
-// int my_array[10];
-// MyRoutine(my_array);
-//
-// int* my_array = new int[10];
-// MyRoutine(gtl::ArraySlice<int>(my_array, 10));
-//
-// MutableArraySlice<T> represents a mutable array of elements, and, like
-// ArraySlice, does not own the backing store. The implicit constructors it
-// provides allow functions not to worry about whether their mutable arguments
-// refer to vectors, arrays, proto2::RepeatedFields, etc.:
-//
-// void MyMutatingRoutine(MutableArraySlice<int> a) {
-// for (int i = 0; i < a.size(); i++) { .. mutate a[i] .. }
-// }
-//
-// std::vector<int> my_vector;
-// MyMutatingRoutine(&my_vector);
-//
-// int my_array[10];
-// MyMutatingRoutine(my_array);
-//
-// int* my_array = new int[10];
-// MyMutatingRoutine(gtl::MutableArraySlice<int>(my_array, 10));
-//
-// MyProto my_proto;
-// for (int i = 0; i < 10; ++i) { my_proto.add_value(i); }
-// MyMutatingRoutine(my_proto.mutable_value());
-
#ifndef TENSORFLOW_CORE_LIB_GTL_ARRAY_SLICE_H_
#define TENSORFLOW_CORE_LIB_GTL_ARRAY_SLICE_H_
-#include <initializer_list>
-#include <type_traits>
-#include <vector>
-
-#include "tensorflow/core/lib/gtl/array_slice_internal.h"
+#include "absl/types/span.h"
+// TODO(timshen): This is kept only because lots of targets transitively depend
+// on it. Remove all targets' dependencies.
#include "tensorflow/core/lib/gtl/inlined_vector.h"
namespace tensorflow {
namespace gtl {
template <typename T>
-class ArraySlice {
- private:
- typedef array_slice_internal::ArraySliceImpl<T> Impl;
-
- public:
- typedef T value_type;
- typedef typename Impl::pointer pointer;
- typedef typename Impl::const_pointer const_pointer;
- typedef typename Impl::reference reference;
- typedef typename Impl::const_reference const_reference;
- typedef typename Impl::iterator iterator;
- typedef typename Impl::const_iterator const_iterator;
- typedef typename Impl::reverse_iterator reverse_iterator;
- typedef typename Impl::const_reverse_iterator const_reverse_iterator;
- typedef typename Impl::size_type size_type;
- typedef typename Impl::difference_type difference_type;
-
- static const size_type npos = Impl::npos;
-
- ArraySlice() : impl_(nullptr, 0) {}
- ArraySlice(const_pointer array, size_type length) : impl_(array, length) {}
-
- // Implicit conversion constructors
- ArraySlice(const std::vector<value_type>& v) // NOLINT(runtime/explicit)
- : impl_(v.data(), v.size()) {}
-
- template <size_t N>
- ArraySlice(const value_type (&a)[N]) // NOLINT(runtime/explicit)
- : impl_(a, N) {}
-
- template <int N>
- ArraySlice(const InlinedVector<value_type, N>& v) // NOLINT(runtime/explicit)
- : impl_(v.data(), v.size()) {}
-
- // The constructor for any class supplying 'data() const' that returns either
- // const T* or a less const-qualified version of it, and 'some_integral_type
- // size() const'. proto2::RepeatedField<T>, string and (since C++11)
- // std::vector<T,A> and std::array<T, N> are examples of this. See
- // array_slice_internal.h for details.
- template <typename V,
- typename = typename Impl::template EnableIfConvertibleFrom<V>>
- ArraySlice(const V& v) // NOLINT(runtime/explicit)
- : impl_(v) {}
-
- // Implicitly constructs an ArraySlice from an initializer list. This makes it
- // possible to pass a brace-enclosed initializer list to a function expecting
- // an ArraySlice:
- // void Process(ArraySlice<int> x);
- // Process({1, 2, 3});
- // The data referenced by the initializer_list must outlive this
- // ArraySlice. For example, "ArraySlice<int> s={1,2};" and "return
- // ArraySlice<int>({3,4});" are errors, as the resulting ArraySlice may
- // reference data that is no longer valid.
- ArraySlice(std::initializer_list<value_type> v) // NOLINT(runtime/explicit)
- : impl_(v.begin(), v.size()) {}
-
- // Substring of another ArraySlice.
- // pos must be non-negative and <= x.length().
- // len must be non-negative and will be pinned to at most x.length() - pos.
- // If len==npos, the substring continues till the end of x.
- ArraySlice(const ArraySlice& x, size_type pos, size_type len)
- : impl_(x.impl_, pos, len) {}
-
- const_pointer data() const { return impl_.data(); }
- size_type size() const { return impl_.size(); }
- size_type length() const { return size(); }
- bool empty() const { return size() == 0; }
-
- void clear() { impl_.clear(); }
-
- const_reference operator[](size_type i) const { return impl_[i]; }
- const_reference at(size_type i) const { return impl_.at(i); }
- const_reference front() const { return impl_.front(); }
- const_reference back() const { return impl_.back(); }
-
- const_iterator begin() const { return impl_.begin(); }
- const_iterator end() const { return impl_.end(); }
- const_reverse_iterator rbegin() const { return impl_.rbegin(); }
- const_reverse_iterator rend() const { return impl_.rend(); }
-
- void remove_prefix(size_type n) { impl_.remove_prefix(n); }
- void remove_suffix(size_type n) { impl_.remove_suffix(n); }
-
- // These relational operators have the same semantics as the
- // std::vector<T> relational operators: they do deep (element-wise)
- // comparisons. Array slices are equal iff their size is the same
- // and all their elements are equal.
- bool operator==(ArraySlice<T> other) const { return impl_ == other.impl_; }
- bool operator!=(ArraySlice<T> other) const { return impl_ != other.impl_; }
-
- private:
- Impl impl_;
-};
-
-// Mutable version of ArraySlice, which allows the clients to mutate the
-// underlying data. It is implicitly convertible to ArraySlice since it provides
-// the data() and size() methods with correct signatures. When a
-// MutableArraySlice is created from a pointer to a container (as opposed to raw
-// memory pointer), the pointer must not be null.
-//
-// A note on const-ness: "mutable" here refers to the mutability of the
-// underlying data, not of the slice itself. It is perfectly reasonable to have
-// a variable of type "const MutableArraySlice<T>"; this means that the bounds
-// of the view on the array cannot be changed, but the underlying data in the
-// array still may be modified. This is akin to a "T* const" pointer, as opposed
-// to a "const T*" pointer (corresponding to a non-const ArraySlice<T>).
-template <typename T>
-class MutableArraySlice {
- private:
- typedef array_slice_internal::MutableArraySliceImpl<T> Impl;
-
- public:
- typedef T value_type;
- typedef typename Impl::pointer pointer;
- typedef typename Impl::const_pointer const_pointer;
- typedef typename Impl::reference reference;
- typedef typename Impl::const_reference const_reference;
- typedef typename Impl::iterator iterator;
- typedef typename Impl::const_iterator const_iterator;
- typedef typename Impl::reverse_iterator reverse_iterator;
- typedef typename Impl::const_reverse_iterator const_reverse_iterator;
- typedef typename Impl::size_type size_type;
- typedef typename Impl::difference_type difference_type;
-
- static const size_type npos = Impl::npos;
-
- MutableArraySlice() : impl_(nullptr, 0) {}
- MutableArraySlice(pointer array, size_type length) : impl_(array, length) {}
-
- // Implicit conversion constructors
- MutableArraySlice(std::vector<value_type>* v) // NOLINT(runtime/explicit)
- : impl_(v->data(), v->size()) {}
-
- template <size_t N>
- MutableArraySlice(value_type (&a)[N]) // NOLINT(runtime/explicit)
- : impl_(a, N) {}
-
- template <int N>
- MutableArraySlice(
- InlinedVector<value_type, N>* v) // NOLINT(runtime/explicit)
- : impl_(v->data(), v->size()) {}
-
- // The constructor for any class supplying 'T* data()' or 'T* mutable_data()'
- // (the former is called if both exist), and 'some_integral_type size()
- // const'. proto2::RepeatedField is an example of this. Also supports string
- // arguments, when T==char. The appropriate ctor is selected using SFINAE. See
- // array_slice_internal.h for details.
- template <typename V,
- typename = typename Impl::template EnableIfConvertibleFrom<V>>
- MutableArraySlice(V* v) // NOLINT(runtime/explicit)
- : impl_(v) {}
+using ArraySlice = absl::Span<const T>;
- // Substring of another MutableArraySlice.
- // pos must be non-negative and <= x.length().
- // len must be non-negative and will be pinned to at most x.length() - pos.
- // If len==npos, the substring continues till the end of x.
- MutableArraySlice(const MutableArraySlice& x, size_type pos, size_type len)
- : impl_(x.impl_, pos, len) {}
-
- // Accessors.
- pointer data() const { return impl_.data(); }
- size_type size() const { return impl_.size(); }
- size_type length() const { return size(); }
- bool empty() const { return size() == 0; }
-
- void clear() { impl_.clear(); }
-
- reference operator[](size_type i) const { return impl_[i]; }
- reference at(size_type i) const { return impl_.at(i); }
- reference front() const { return impl_.front(); }
- reference back() const { return impl_.back(); }
-
- iterator begin() const { return impl_.begin(); }
- iterator end() const { return impl_.end(); }
- reverse_iterator rbegin() const { return impl_.rbegin(); }
- reverse_iterator rend() const { return impl_.rend(); }
-
- void remove_prefix(size_type n) { impl_.remove_prefix(n); }
- void remove_suffix(size_type n) { impl_.remove_suffix(n); }
-
- bool operator==(ArraySlice<T> other) const {
- return ArraySlice<T>(*this) == other;
- }
- bool operator!=(ArraySlice<T> other) const {
- return ArraySlice<T>(*this) != other;
- }
-
- private:
- Impl impl_;
-};
-
-template <typename T>
-const typename ArraySlice<T>::size_type ArraySlice<T>::npos;
template <typename T>
-const typename MutableArraySlice<T>::size_type MutableArraySlice<T>::npos;
+using MutableArraySlice = absl::Span<T>;
} // namespace gtl
} // namespace tensorflow
diff --git a/tensorflow/core/lib/gtl/array_slice_internal.h b/tensorflow/core/lib/gtl/array_slice_internal.h
deleted file mode 100644
index 689dd8a646..0000000000
--- a/tensorflow/core/lib/gtl/array_slice_internal.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// NOT FOR INCLUSION BY CLIENT CODE. This file is only to be included by
-// array_slice.h.
-
-// Helper functions and templates for ArraySlice.
-
-#ifndef TENSORFLOW_LIB_GTL_ARRAY_SLICE_INTERNAL_H_
-#define TENSORFLOW_LIB_GTL_ARRAY_SLICE_INTERNAL_H_
-
-#include <stddef.h>
-#include <algorithm>
-#include <iterator>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
-#include "tensorflow/core/platform/logging.h"
-
-namespace tensorflow {
-namespace gtl {
-namespace array_slice_internal {
-
-// Template logic for generic constructors.
-
-// Wrappers whose Get() delegates to the appropriate method of a container, and
-// is defined when this method exists. Delegates to the const method if C is a
-// const type.
-struct Data {
- template <typename C>
- static decltype(std::declval<C>().data()) Get(C* v) {
- return v->data();
- }
-};
-
-struct MutableData {
- template <typename C>
- static decltype(std::declval<C>().mutable_data()) Get(C* v) {
- return v->mutable_data();
- }
-};
-
-struct Size {
- template <typename C>
- static decltype(std::declval<C>().size()) Get(C* v) {
- return v->size();
- }
-};
-
-struct MutableStringData {
- // Defined only for string.
- static char* Get(string* v) { return v->empty() ? nullptr : &*v->begin(); }
-};
-
-// Checks whether M::Get(C*) is defined and has a return type R such that
-// Checker::valid<R>()==true.
-template <typename M, typename Checker, typename C>
-struct HasGetHelper : public M {
- private:
- struct None {};
- // M::Get is selected when it is viable. Get(...) is selected otherwise.
- using M::Get;
- static None Get(...);
-
- public:
- static constexpr bool HasGet() {
- using Result = decltype(Get(std::declval<C*>()));
- return !std::is_same<Result, None>() && Checker::template valid<Result>();
- }
-};
-
-// Defines HasGet() for a particular method, container, and checker. If
-// HasGet()==true, provides Get() that delegates to the method.
-template <typename M, typename Checker, typename C,
- bool /*has_get*/ = HasGetHelper<M, Checker, C>::HasGet()>
-struct Wrapper {
- static constexpr bool HasGet() { return false; }
-};
-
-template <typename M, typename Checker, typename C>
-struct Wrapper<M, Checker, C, true> {
- static constexpr bool HasGet() { return true; }
- static decltype(M::Get(std::declval<C*>())) Get(C* v) { return M::Get(v); }
-};
-
-// Type checker for a method returning an integral value.
-struct SizeChecker {
- template <typename R>
- static constexpr bool valid() {
- return std::is_integral<R>::value;
- }
-};
-
-// Type checker for a method returning either a pointer to T or a less const
-// version of that.
-template <typename T>
-struct DataChecker {
- // We want to enable conversion from std::vector<T*> to ArraySlice<const T*>
- // but
- // disable conversion from std::vector<Derived> to ArraySlice<Base>. Here we
- // use
- // the fact that U** is convertible to Q* const* if and only if Q is the same
- // type or a more cv-qualified version of U.
- template <typename R>
- static constexpr bool valid() {
- return std::is_convertible<R*, T* const*>::value;
- }
-};
-
-// Aliases to A if A::HasGet()==true, or to B otherwise.
-template <typename A, typename B>
-using FirstWithGet = typename std::conditional<A::HasGet(), A, B>::type;
-
-// Wraps C::data() const, returning a pointer to const data.
-template <typename T, typename C>
-using ContainerData = Wrapper<Data, DataChecker<const T>, const C>;
-
-// Wraps a method returning a pointer to mutable data. Prefers data() over
-// mutable_data(), and handles strings when T==char. If data() returns a pointer
-// to mutable data, it is most likely overloaded, but may also be a single
-// method 'T* C::data() const' in a non-STL-compliant container.
-template <typename T, typename C>
-using ContainerMutableData =
- FirstWithGet<Wrapper<Data, DataChecker<T>, C>,
- FirstWithGet<Wrapper<MutableData, DataChecker<T>, C>,
- Wrapper<MutableStringData, DataChecker<T>, C>>>;
-
-// Wraps C::size() const.
-template <typename C>
-using ContainerSize = Wrapper<Size, SizeChecker, const C>;
-
-// Implementation class for ArraySlice and MutableArraySlice. In the case of
-// ArraySlice, T will be a const type; for MutableArraySlice, T will be a
-// mutable type.
-template <typename T>
-class ArraySliceImplBase {
- public:
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef pointer iterator;
- typedef const_pointer const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
-
- static const size_type npos = static_cast<size_type>(-1);
-
- ArraySliceImplBase(pointer array, size_type length)
- : ptr_(array), length_(length) {}
-
- // Substring of another ArraySlice.
- // pos must be non-negative and <= x.length().
- // len must be non-negative and will be pinned to at most x.length() - pos.
- ArraySliceImplBase(const ArraySliceImplBase& x, size_type pos, size_type len)
- : ptr_(x.ptr_ + pos), length_(std::min(x.length_ - pos, len)) {}
-
- // Some of the const methods below return pointers and references to mutable
- // data. This is only the case in this internal class; ArraySlice and
- // MutableArraySlice provide deep-constness.
-
- pointer data() const { return ptr_; }
- size_type size() const { return length_; }
-
- void clear() {
- ptr_ = nullptr;
- length_ = 0;
- }
-
- reference operator[](size_type i) const { return ptr_[i]; }
- reference at(size_type i) const {
- DCHECK_LT(i, length_);
- return ptr_[i];
- }
- reference front() const {
- DCHECK_GT(length_, 0);
- return ptr_[0];
- }
- reference back() const {
- DCHECK_GT(length_, 0);
- return ptr_[length_ - 1];
- }
-
- void remove_prefix(size_type n) {
- DCHECK_GE(length_, n);
- ptr_ += n;
- length_ -= n;
- }
- void remove_suffix(size_type n) {
- DCHECK_GE(length_, n);
- length_ -= n;
- }
-
- iterator begin() const { return ptr_; }
- iterator end() const { return ptr_ + length_; }
- reverse_iterator rbegin() const { return reverse_iterator(end()); }
- reverse_iterator rend() const { return reverse_iterator(begin()); }
-
- bool operator==(const ArraySliceImplBase& other) const {
- if (size() != other.size()) return false;
- if (data() == other.data()) return true;
- return std::equal(data(), data() + size(), other.data());
- }
- bool operator!=(const ArraySliceImplBase& other) const {
- return !(*this == other);
- }
-
- private:
- pointer ptr_;
- size_type length_;
-};
-
-template <typename T>
-class ArraySliceImpl : public ArraySliceImplBase<const T> {
- public:
- using ArraySliceImplBase<const T>::ArraySliceImplBase;
-
- // Defined iff the data and size accessors for the container C have been
- // defined.
- template <typename C>
- using EnableIfConvertibleFrom =
- typename std::enable_if<ContainerData<T, C>::HasGet() &&
- ContainerSize<C>::HasGet()>::type;
-
- // Constructs from a container when EnableIfConvertibleFrom is
- // defined. std::addressof handles types with overloaded operator&.
- template <typename C>
- explicit ArraySliceImpl(const C& v)
- : ArraySliceImplBase<const T>(ContainerData<T, C>::Get(std::addressof(v)),
- ContainerSize<C>::Get(std::addressof(v))) {}
-};
-
-template <typename T>
-class MutableArraySliceImpl : public ArraySliceImplBase<T> {
- public:
- using ArraySliceImplBase<T>::ArraySliceImplBase;
-
- template <typename C>
- using EnableIfConvertibleFrom =
- typename std::enable_if<ContainerMutableData<T, C>::HasGet() &&
- ContainerSize<C>::HasGet()>::type;
-
- template <typename C>
- explicit MutableArraySliceImpl(C* v)
- : ArraySliceImplBase<T>(ContainerMutableData<T, C>::Get(v),
- ContainerSize<C>::Get(v)) {}
-};
-
-} // namespace array_slice_internal
-} // namespace gtl
-} // namespace tensorflow
-
-#endif // TENSORFLOW_LIB_GTL_ARRAY_SLICE_INTERNAL_H_
diff --git a/tensorflow/core/lib/gtl/array_slice_test.cc b/tensorflow/core/lib/gtl/array_slice_test.cc
deleted file mode 100644
index c798a488cb..0000000000
--- a/tensorflow/core/lib/gtl/array_slice_test.cc
+++ /dev/null
@@ -1,664 +0,0 @@
-/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "tensorflow/core/lib/gtl/array_slice.h"
-
-#include <algorithm>
-#include <array>
-#include <string>
-#include <vector>
-
-#include "tensorflow/core/lib/gtl/inlined_vector.h"
-#include "tensorflow/core/lib/gtl/stl_util.h"
-#include "tensorflow/core/platform/macros.h"
-#include "tensorflow/core/platform/test.h"
-#include "tensorflow/core/platform/types.h"
-
-namespace tensorflow {
-namespace gtl {
-namespace {
-
-typedef ArraySlice<int> IntSlice;
-typedef ArraySlice<char> CharSlice;
-typedef MutableArraySlice<int> MutableIntSlice;
-typedef MutableArraySlice<char> MutableCharSlice;
-typedef std::vector<int> IntVec;
-
-// Append 0..len-1 to *v
-template <typename Vector>
-static void Fill(Vector* v, int len, int offset = 0) {
- for (int i = 0; i < len; i++) {
- v->push_back(i + offset);
- }
-}
-
-static void TestHelper(const IntSlice& vorig, const IntVec& vec) {
- IntSlice other; // To test the assignment return value.
- IntSlice v = other = vorig;
- const int len = vec.size();
- EXPECT_EQ(v.size(), vec.size());
-
- for (int i = 0; i < len; i++) {
- EXPECT_EQ(v[i], vec[i]);
- EXPECT_EQ(v.at(i), vec[i]);
- }
- EXPECT_EQ(v.begin(), gtl::vector_as_array(&vec));
-
- int counter = 0;
- for (IntSlice::iterator it = v.begin(); it != v.end(); ++it) {
- EXPECT_EQ(counter, *it);
- counter++;
- }
- EXPECT_EQ(counter, len);
-
- counter = 0;
- for (IntSlice::const_iterator it = v.begin(); it != v.end(); ++it) {
- EXPECT_EQ(counter, *it);
- counter++;
- }
- EXPECT_EQ(counter, len);
-
- if (len > 0) {
- EXPECT_EQ(0, v.front());
- EXPECT_EQ(len - 1, v.back());
- v.remove_suffix(1);
- EXPECT_EQ(len - 1, v.size());
- for (size_t i = 0; i < v.size(); ++i) {
- EXPECT_EQ(i, v[i]);
- }
- if (len > 1) {
- v.remove_prefix(1);
- EXPECT_EQ(len - 2, v.size());
- for (size_t i = 0; i < v.size(); ++i) {
- EXPECT_EQ(i + 1, v[i]);
- }
- }
- }
-}
-
-// The element access test that is applicable both when MutableArraySlice is
-// const and when it's not.
-template <class V>
-void MutableTestHelperTemplated(V v, int* ptr, const int len) {
- CHECK_EQ(v.size(), len);
-
- for (int i = 0; i < len; i++) {
- EXPECT_EQ(ptr + i, &v[i]);
- EXPECT_EQ(ptr + i, &v.at(i));
- }
- EXPECT_EQ(ptr, v.begin());
- EXPECT_EQ(ptr + len, v.end());
- EXPECT_EQ(ptr, v.data());
-
- int counter = 0;
- for (MutableIntSlice::const_iterator it = v.begin(); it != v.end(); ++it) {
- EXPECT_EQ(ptr + counter, &*it);
- counter++;
- }
- EXPECT_EQ(counter, len);
-
- EXPECT_EQ(len, std::distance(v.rbegin(), v.rend()));
-
- if (len > 0) {
- EXPECT_EQ(ptr, &v.front());
- EXPECT_EQ(ptr + len - 1, &v.back());
- EXPECT_EQ(ptr + len - 1, &*v.rbegin());
- EXPECT_EQ(ptr, &*(v.rend() - 1));
- }
-}
-
-static void MutableTestHelper(const MutableIntSlice& vorig, int* ptr,
- const int len) {
- // Test the data accessors both when the MutableArraySlice is declared const,
- // and when it is not.
- MutableTestHelperTemplated<const MutableIntSlice&>(vorig, ptr, len);
- MutableTestHelperTemplated<MutableIntSlice>(vorig, ptr, len);
-
- MutableIntSlice other; // To test the assignment return value.
- MutableIntSlice v = other = vorig;
- EXPECT_EQ(ptr, v.data());
-
- int counter = 0;
- for (MutableIntSlice::iterator it = v.begin(); it != v.end(); ++it) {
- EXPECT_EQ(ptr + counter, &*it);
- counter++;
- }
- EXPECT_EQ(counter, len);
-
- if (len > 0) {
- // Test that elements are assignable.
- v[0] = 1;
- v.front() = 2;
- v.back() = 5;
- *v.data() = 4;
- std::fill(v.begin(), v.end(), 5);
- std::fill(v.rbegin(), v.rend(), 6);
- // Test size-changing methods.
- v.remove_suffix(1);
- EXPECT_EQ(len - 1, v.size());
- for (size_t i = 0; i < v.size(); ++i) {
- EXPECT_EQ(ptr + i, &v[i]);
- }
- if (len > 1) {
- v.remove_prefix(1);
- EXPECT_EQ(len - 2, v.size());
- for (size_t i = 0; i < v.size(); ++i) {
- EXPECT_EQ(ptr + i + 1, &v[i]);
- }
- }
- }
-}
-
-template <typename Vector>
-static void TestImplicitConversion(const IntSlice& v, const Vector& vec) {
- EXPECT_EQ(v.size(), vec.size());
- for (size_t i = 0; i < v.size(); i++) {
- EXPECT_EQ(v[i], vec[i]);
- }
-}
-
-template <typename Vector>
-static void TestImplicitConversion(const CharSlice& v, const Vector& vec) {
- TestImplicitConversion(IntVec(v.begin(), v.end()), vec);
-}
-
-static void TestImplicitConversion(const MutableIntSlice& v, const int* data,
- int size) {
- EXPECT_EQ(size, v.size());
- for (size_t i = 0; i < v.size(); i++) {
- EXPECT_EQ(data + i, &v[i]);
- }
-}
-
-static void TestImplicitConversion(const MutableCharSlice& v, const char* data,
- int size) {
- EXPECT_EQ(size, v.size());
- for (size_t i = 0; i < v.size(); i++) {
- EXPECT_EQ(data + i, &v[i]);
- }
-}
-// A struct supplying the data(), mutable_data() and size() methods, just like
-// e.g. proto2::RepeatedField.
-struct RepeatedField {
- std::vector<int> storage;
- const int* data() const { return storage.data(); }
- int* mutable_data() { return storage.data(); }
- int size() const { return storage.size(); }
-};
-
-// A struct supplying the data() (both mutable and const versions) and
-// size(). It also supplies mutable_data() but we test that data() is selected
-// instead.
-struct ContainerWithOverloads {
- std::vector<int> storage;
- std::vector<int> wrong_storage;
- const int* data() const { return storage.data(); }
- int* data() { return storage.data(); }
- // MutableArraySlice should not call mutable_data(), preferring data()
- // instead.
- int* mutable_data() { return wrong_storage.data(); }
- int size() const { return storage.size(); }
-};
-
-// A struct supplying data() and size() methods.
-struct ContainerWithShallowConstData {
- std::vector<int> storage;
- int* data() const { return const_cast<int*>(storage.data()); }
- int size() const { return storage.size(); }
-};
-
-TEST(IntSlice, Simple) {
- for (int len = 0; len < 20; len++) {
- IntVec vec;
- Fill(&vec, len);
- TestHelper(IntSlice(vec), vec);
- TestHelper(IntSlice(vec.data(), vec.size()), vec);
- }
-}
-
-TEST(IntSlice, WithPosAndLen) {
- IntVec vec;
- Fill(&vec, 20);
- for (size_t len = 0; len < vec.size(); len++) {
- IntVec subvec(vec.begin(), vec.begin() + len);
- TestImplicitConversion(IntSlice(vec, 0, len), subvec);
- TestImplicitConversion(IntSlice(IntSlice(vec), 0, len), subvec);
- }
- EXPECT_EQ(0, IntSlice(vec, 0, 0).size());
- EXPECT_EQ(0, IntSlice(IntSlice(vec), 0, 0).size());
- TestImplicitConversion(IntSlice(vec, 0, IntSlice::npos), vec);
-}
-
-TEST(IntSlice, Clear) {
- for (int len = 0; len < 20; len++) {
- IntVec vec;
- Fill(&vec, len);
- IntSlice v(vec);
- v.clear();
- EXPECT_EQ(0, v.size());
- EXPECT_EQ(v.begin(), v.end());
- }
-}
-
-TEST(IntSlice, Swap) {
- for (int l1 = 0; l1 < 20; l1++) {
- for (int l2 = 0; l2 < 20; l2++) {
- IntVec avec, bvec;
- Fill(&avec, l1);
- Fill(&bvec, l2, 100);
- IntSlice a(avec), b(bvec);
- using std::swap;
- swap(a, b);
- EXPECT_EQ(l1, b.size());
- EXPECT_EQ(l2, a.size());
- for (int i = 0; i < l1; i++) {
- EXPECT_EQ(i, b[i]);
- }
- for (int i = 0; i < l2; i++) {
- EXPECT_EQ(100 + i, a[i]);
- }
- }
- }
-}
-
-TEST(IntSlice, ImplicitConversion) {
- for (int len = 0; len < 20; len++) {
- IntVec vec;
- Fill(&vec, len);
- IntSlice slice;
- slice = vec;
- TestImplicitConversion(vec, vec);
- TestImplicitConversion(slice, vec);
- TestImplicitConversion(IntSlice(vec.data(), vec.size()), vec);
- }
-}
-
-TEST(IntSlice, InlinedVectorConversion) {
- for (int len = 0; len < 20; len++) {
- InlinedVector<int, 4> inline_vec;
- for (int i = 0; i < len; i++) {
- inline_vec.push_back(i);
- }
- IntVec vec;
- Fill(&vec, len);
- IntSlice v = inline_vec; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(inline_vec, vec);
- }
-}
-
-TEST(IntSlice, StaticArrayConversion) {
- int array[20];
- IntVec vec;
- Fill(&vec, TF_ARRAYSIZE(array));
- std::copy(vec.begin(), vec.end(), array);
- IntSlice v = array; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(array, vec);
-}
-
-TEST(IntSlice, StdArrayConversion) {
- std::array<int, 20> array;
- IntVec vec;
- Fill(&vec, array.size());
- std::copy(vec.begin(), vec.end(), array.begin());
-
- // Check assignment.
- {
- IntSlice v = array;
- static_cast<void>(v);
- }
-
- // Check sub-slice initialization.
- {
- IntSlice v = {array, 10, 15};
- static_cast<void>(v);
- }
-
- TestImplicitConversion(array, vec);
-}
-
-// Values according to the Fill function.
-static const int test_const_array[] = {0, 1, 2};
-
-TEST(IntSlice, ConstStaticArrayConversion) {
- IntVec vec;
- Fill(&vec, TF_ARRAYSIZE(test_const_array));
- IntSlice v = test_const_array; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(test_const_array, vec);
-}
-
-TEST(IntSlice, RepeatedFieldConversion) {
- RepeatedField repeated_field;
- IntVec vec;
- Fill(&vec, 20);
- repeated_field.storage = vec;
- IntSlice v = repeated_field; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(repeated_field, vec);
-}
-
-TEST(IntSlice, ContainerWithOverloadsConversion) {
- ContainerWithOverloads container;
- Fill(&container.storage, 20);
- container.wrong_storage.resize(container.size());
- IntSlice v = container; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(container, container.storage);
-}
-
-TEST(IntSlice, ContainerWithShallowConstDataConversion) {
- ContainerWithShallowConstData container;
- Fill(&container.storage, 20);
- IntSlice v = container; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(container, container.storage);
-}
-
-TEST(IntSlice, MutableIntSliceConversion) {
- IntVec vec(20);
- IntSlice slice = MutableIntSlice(&vec);
- EXPECT_EQ(vec.size(), slice.size());
- EXPECT_EQ(vec.data(), slice.data());
-}
-
-TEST(IntSlice, Equality) {
- IntVec vec1(20);
- IntVec vec2(20);
- // These two slices are from different vectors, but have the same
- // size and have the same elements (right now). They should
- // compare equal.
- const IntSlice from1(vec1);
- const IntSlice from2(vec2);
- EXPECT_EQ(from1, from1);
- EXPECT_EQ(from1, from2);
-
- // This verifies that MutableArraySlices can be compared freely with
- // ArraySlices.
- const MutableIntSlice mutable_from1(&vec1);
- const MutableIntSlice mutable_from2(&vec2);
- EXPECT_EQ(from1, mutable_from1);
- EXPECT_EQ(mutable_from1, from1);
- EXPECT_EQ(mutable_from1, mutable_from2);
- EXPECT_EQ(mutable_from2, mutable_from1);
-
- // With a different size, the array slices should not be equal.
- EXPECT_NE(from1, IntSlice(from1, 0, from1.size() - 1));
-
- // With different contents, the array slices should not be equal.
- ++vec2.back();
- EXPECT_NE(from1, from2);
-}
-
-// Compile-asserts that the argument has the expected type.
-template <typename Expected, typename T>
-void CheckType(const T& value) {
- ::testing::StaticAssertTypeEq<Expected, T>();
-}
-
-TEST(IntSlice, ExposesContainerTypesAndConsts) {
- IntSlice slice;
- const IntSlice const_slice;
- CheckType<IntSlice::iterator>(slice.begin());
- CheckType<IntSlice::const_iterator>(const_slice.end());
- CheckType<IntSlice::const_reverse_iterator>(const_slice.rbegin());
- CheckType<IntSlice::reverse_iterator>(slice.rend());
- ::testing::StaticAssertTypeEq<int, IntSlice::value_type>();
- ::testing::StaticAssertTypeEq<const int*, IntSlice::pointer>();
- ::testing::StaticAssertTypeEq<const int&, IntSlice::const_reference>();
- EXPECT_EQ(static_cast<IntSlice::size_type>(-1), IntSlice::npos);
-}
-
-void TestEmpty(IntSlice slice) { ASSERT_TRUE(slice.empty()); }
-
-void TestRange(IntSlice slice, int from, int to) {
- ASSERT_EQ(to - from + 1, slice.size());
- for (size_t i = 0; i < slice.size(); ++i) {
- EXPECT_EQ(from + i, slice[i]);
- }
-}
-
-TEST(IntSlice, InitializerListConversion) {
- TestEmpty({});
- TestRange({1}, 1, 1);
- TestRange({10, 11, 12, 13}, 10, 13);
-}
-
-TEST(CharSlice, StringConversion) {
- IntVec vec;
- Fill(&vec, 20);
- string str(vec.begin(), vec.end());
- CharSlice v = str; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(str, vec);
-}
-
-TEST(IntPtrSlice, ConstConversion) {
- int one = 1;
- int two = 2;
- std::vector<int*> vec;
- vec.push_back(&one);
- vec.push_back(&two);
- ArraySlice<const int*> v = vec;
- ASSERT_EQ(2, v.size());
- EXPECT_EQ(&one, v[0]);
- EXPECT_EQ(&two, v[1]);
-}
-
-TEST(MutableIntSlice, Simple) {
- for (int len = 0; len < 20; len++) {
- IntVec vec(len);
- MutableTestHelper(MutableIntSlice(&vec), vec.data(), len);
- MutableTestHelper(MutableIntSlice(vec.data(), vec.size()), vec.data(), len);
- }
-}
-
-TEST(MutableIntSlice, WithPosAndLen) {
- IntVec vec(20);
- for (size_t len = 0; len < vec.size(); len++) {
- TestImplicitConversion(MutableIntSlice(&vec, 0, len), vec.data(), len);
- TestImplicitConversion(MutableIntSlice(MutableIntSlice(&vec), 0, len),
- vec.data(), len);
- }
- EXPECT_EQ(0, MutableIntSlice(&vec, 0, 0).size());
- EXPECT_EQ(0, MutableIntSlice(MutableIntSlice(&vec), 0, 0).size());
- TestImplicitConversion(MutableIntSlice(&vec, 0, MutableIntSlice::npos),
- vec.data(), vec.size());
-}
-
-TEST(MutableIntSlice, Clear) {
- for (int len = 0; len < 20; len++) {
- IntVec vec(len);
- MutableIntSlice v(&vec);
- v.clear();
- EXPECT_EQ(0, v.size());
- EXPECT_EQ(v.begin(), v.end());
- }
-}
-
-TEST(MutableIntSlice, Swap) {
- for (int l1 = 0; l1 < 20; l1++) {
- for (int l2 = 0; l2 < 20; l2++) {
- IntVec avec(l1), bvec(l2);
- MutableIntSlice a(&avec), b(&bvec);
- using std::swap;
- swap(a, b);
- EXPECT_EQ(l1, b.size());
- EXPECT_EQ(l2, a.size());
- for (int i = 0; i < l1; i++) {
- EXPECT_EQ(&avec[i], &b[i]);
- }
- for (int i = 0; i < l2; i++) {
- EXPECT_EQ(&bvec[i], &a[i]);
- }
- }
- }
-}
-
-TEST(MutableIntSlice, ImplicitConversion) {
- for (int len = 0; len < 20; len++) {
- IntVec vec(len);
- MutableIntSlice slice;
- slice = &vec;
- TestImplicitConversion(&vec, vec.data(), len);
- TestImplicitConversion(slice, vec.data(), len);
- TestImplicitConversion(MutableIntSlice(vec.data(), vec.size()), vec.data(),
- len);
- }
-}
-
-TEST(MutableIntSlice, InlinedVectorConversion) {
- for (int len = 0; len < 20; len++) {
- InlinedVector<int, 4> inline_vec;
- for (int i = 0; i < len; i++) {
- inline_vec.push_back(i);
- }
- MutableIntSlice v = &inline_vec; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(&inline_vec, inline_vec.data(), inline_vec.size());
- }
-}
-
-TEST(MutableIntSlice, StaticArrayConversion) {
- int array[20];
- MutableIntSlice v = array; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(array, array, TF_ARRAYSIZE(array));
-}
-
-TEST(MutableIntSlice, StdArrayConversion) {
- std::array<int, 20> array;
-
- // Check assignment.
- {
- MutableIntSlice v = &array;
- static_cast<void>(v);
- }
-
- // Check sub-slice initialization.
- {
- MutableIntSlice v = {&array, 10, 15};
- static_cast<void>(v);
- }
-
- TestImplicitConversion(&array, &array[0], array.size());
-}
-
-TEST(MutableIntSlice, RepeatedFieldConversion) {
- RepeatedField repeated_field;
- Fill(&repeated_field.storage, 20);
- MutableIntSlice v = &repeated_field; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(&repeated_field, repeated_field.storage.data(),
- repeated_field.storage.size());
-}
-
-TEST(MutableIntSlice, ContainerWithOverloadsConversion) {
- ContainerWithOverloads container;
- Fill(&container.storage, 20);
- container.wrong_storage.resize(container.size());
- MutableIntSlice v = &container; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(&container, container.storage.data(),
- container.storage.size());
-}
-
-TEST(MutableIntSlice, ContainerWithShallowConstDataConversion) {
- ContainerWithShallowConstData container;
- Fill(&container.storage, 20);
- MutableIntSlice v = &container; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(&container, container.storage.data(),
- container.storage.size());
-}
-
-TEST(MutableIntSlice, TypedefsAndConstants) {
- ::testing::StaticAssertTypeEq<int, MutableIntSlice::value_type>();
- ::testing::StaticAssertTypeEq<int*, MutableIntSlice::pointer>();
- ::testing::StaticAssertTypeEq<const int*, MutableIntSlice::const_pointer>();
- ::testing::StaticAssertTypeEq<int&, MutableIntSlice::reference>();
- ::testing::StaticAssertTypeEq<const int&, MutableIntSlice::const_reference>();
-
- EXPECT_EQ(static_cast<MutableIntSlice::size_type>(-1), MutableIntSlice::npos);
-}
-
-TEST(MutableIntSlice, IteratorsAndReferences) {
- auto accept_pointer = [](int* x) {};
- auto accept_reference = [](int& x) {};
- auto accept_iterator = [](MutableIntSlice::iterator x) {};
- auto accept_reverse_iterator = [](MutableIntSlice::reverse_iterator x) {};
-
- int a[1];
- MutableIntSlice s = a;
-
- accept_pointer(s.data());
- accept_iterator(s.begin());
- accept_iterator(s.end());
- accept_reverse_iterator(s.rbegin());
- accept_reverse_iterator(s.rend());
-
- accept_reference(s[0]);
- accept_reference(s.at(0));
- accept_reference(s.front());
- accept_reference(s.back());
-}
-
-TEST(MutableIntSlice, IteratorsAndReferences_Const) {
- auto accept_pointer = [](int* x) {};
- auto accept_reference = [](int& x) {};
- auto accept_iterator = [](MutableIntSlice::iterator x) {};
- auto accept_reverse_iterator = [](MutableIntSlice::reverse_iterator x) {};
-
- int a[1];
- const MutableIntSlice s = a;
-
- accept_pointer(s.data());
- accept_iterator(s.begin());
- accept_iterator(s.end());
- accept_reverse_iterator(s.rbegin());
- accept_reverse_iterator(s.rend());
-
- accept_reference(s[0]);
- accept_reference(s.at(0));
- accept_reference(s.front());
- accept_reference(s.back());
-}
-
-bool TestMutableOverload(MutableIntSlice slice) { return false; }
-
-bool TestMutableOverload(MutableCharSlice slice) { return true; }
-
-TEST(MutableCharSlice, StringConversion) {
- for (int len = 0; len < 20; len++) {
- string str(len, '\0');
- MutableCharSlice v = &str; // Test assignment
- static_cast<void>(v);
- TestImplicitConversion(v, str.data(), str.size());
- }
- // Verify that only the correct overload is feasible. Note that this would
- // fail if the string ctor was declared simply as MutableArraySlice(string*),
- // since in that case both overloads would be feasible.
- string str;
- EXPECT_TRUE(TestMutableOverload(&str));
-
- // Avoid warning "unused function 'TestMutableOverload'"
- int a[1];
- EXPECT_FALSE(TestMutableOverload(a));
-}
-
-} // namespace
-} // namespace gtl
-} // namespace tensorflow