#define LLVM_ADT_ARRAYREF_H
#include "llvm/ADT/None.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
/// The number of elements.
size_type Length;
- /// \brief A dummy "optional" type that is only created by implicit
- /// conversion from a reference to T.
- ///
- /// This type must *only* be used in a function argument or as a copy of
- /// a function argument, as otherwise it will hold a pointer to a temporary
- /// past that temporaries' lifetime.
- struct TRefOrNothing {
- const T *TPtr;
-
- TRefOrNothing() : TPtr(nullptr) {}
- TRefOrNothing(const T &TRef) : TPtr(&TRef) {}
- };
-
public:
/// @name Constructors
/// @{
/*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N])
: Data(Arr), Length(N) {}
-#if LLVM_HAS_INITIALIZER_LISTS
/// Construct an ArrayRef from a std::initializer_list.
/*implicit*/ ArrayRef(const std::initializer_list<T> &Vec)
- : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()),
+ : Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()),
Length(Vec.size()) {}
-#endif
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
/// ensure that only ArrayRefs of pointers can be converted.
std::is_convertible<U *const *, T const *>::value>::type* = 0)
: Data(A.data()), Length(A.size()) {}
- /// Construct an ArrayRef<T*> from an ArrayRef<U*> where T is a super class
- /// of U. This uses SFINAE to ensure that only ArrayRefs with this property
- /// can be converted. This is an upcasting constructor.
- template <typename U>
- ArrayRef(const ArrayRef<U> &A,
- typename std::enable_if<std::is_base_of<
- typename std::remove_pointer<T>::type,
- typename std::remove_pointer<U>::type>::value>::type * = 0)
- : Data(reinterpret_cast<T const *>(A.data())), Length(A.size()) {}
+ /// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is
+ /// templated in order to avoid instantiating SmallVectorTemplateCommon<T>
+ /// whenever we copy-construct an ArrayRef.
+ template<typename U, typename DummyT>
+ /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<U*, DummyT> &Vec,
+ typename std::enable_if<
+ std::is_convertible<U *const *,
+ T const *>::value>::type* = 0)
+ : Data(Vec.data()), Length(Vec.size()) {
+ }
+
+ /// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE
+ /// to ensure that only vectors of pointers can be converted.
+ template<typename U, typename A>
+ ArrayRef(const std::vector<U *, A> &Vec,
+ typename std::enable_if<
+ std::is_convertible<U *const *, T const *>::value>::type* = 0)
+ : Data(Vec.data()), Length(Vec.size()) {}
/// @}
/// @name Simple Operations
bool equals(ArrayRef RHS) const {
if (Length != RHS.Length)
return false;
- // Don't use std::equal(), since it asserts in MSVC on nullptr iterators.
- for (auto L = begin(), LE = end(), R = RHS.begin(); L != LE; ++L, ++R)
- // Match std::equal() in using == (instead of !=) to minimize API
- // requirements of ArrayRef'ed types.
- if (!(*L == *R))
- return false;
- return true;
+ if (Length == 0)
+ return true;
+ return std::equal(begin(), end(), RHS.begin());
}
/// slice(n) - Chop off the first N elements of the array.
return std::vector<T>(Data, Data+Length);
}
- /// @}
- /// @{
- /// @name Convenience methods
-
- /// @brief Predicate for testing that the array equals the exact sequence of
- /// arguments.
- ///
- /// Will return false if the size is not equal to the exact number of
- /// arguments given or if the array elements don't equal the argument
- /// elements in order. Currently supports up to 16 arguments, but can
- /// easily be extended.
- bool equals(TRefOrNothing Arg0 = TRefOrNothing(),
- TRefOrNothing Arg1 = TRefOrNothing(),
- TRefOrNothing Arg2 = TRefOrNothing(),
- TRefOrNothing Arg3 = TRefOrNothing(),
- TRefOrNothing Arg4 = TRefOrNothing(),
- TRefOrNothing Arg5 = TRefOrNothing(),
- TRefOrNothing Arg6 = TRefOrNothing(),
- TRefOrNothing Arg7 = TRefOrNothing(),
- TRefOrNothing Arg8 = TRefOrNothing(),
- TRefOrNothing Arg9 = TRefOrNothing(),
- TRefOrNothing Arg10 = TRefOrNothing(),
- TRefOrNothing Arg11 = TRefOrNothing(),
- TRefOrNothing Arg12 = TRefOrNothing(),
- TRefOrNothing Arg13 = TRefOrNothing(),
- TRefOrNothing Arg14 = TRefOrNothing(),
- TRefOrNothing Arg15 = TRefOrNothing()) {
- TRefOrNothing Args[] = {Arg0, Arg1, Arg2, Arg3, Arg4, Arg5,
- Arg6, Arg7, Arg8, Arg9, Arg10, Arg11,
- Arg12, Arg13, Arg14, Arg15};
- if (size() > array_lengthof(Args))
- return false;
-
- for (unsigned i = 0, e = size(); i != e; ++i)
- if (Args[i].TPtr == nullptr || (*this)[i] != *Args[i].TPtr)
- return false;
-
- // Either the size is exactly as many args, or the next arg must be null.
- return size() == array_lengthof(Args) || Args[size()].TPtr == nullptr;
- }
-
/// @}
};
return MutableArrayRef<T>(data()+N, M);
}
+ MutableArrayRef<T> drop_back(unsigned N) const {
+ assert(this->size() >= N && "Dropping more elements than exist");
+ return slice(0, this->size() - N);
+ }
+
/// @}
/// @name Operator Overloads
/// @{