Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 13 additions & 38 deletions llvm/include/llvm/ADT/ArrayRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,19 @@ namespace llvm {
assert(begin <= end);
}

/// Construct an ArrayRef from a SmallVector. This is templated in order to
/// avoid instantiating SmallVectorTemplateCommon<T> whenever we
/// copy-construct an ArrayRef.
template<typename U>
/*implicit*/ ArrayRef(const SmallVectorTemplateCommon<T, U> &Vec)
: Data(Vec.data()), Length(Vec.size()) {
}

/// Construct an ArrayRef from a std::vector.
template<typename A>
/*implicit*/ ArrayRef(const std::vector<T, A> &Vec)
: Data(Vec.data()), Length(Vec.size()) {}
/// Construct an ArrayRef from a type that has a data() method that returns
/// a pointer convertible to const T *.
template <
typename C,
typename = std::enable_if_t<
std::conjunction_v<
std::is_convertible<
decltype(std::declval<const C &>().data()) *,
const T *const *>,
std::is_integral<decltype(std::declval<const C &>().size())>>,
void>>
/*implicit*/ constexpr ArrayRef(const C &V)
: Data(V.data()), Length(V.size()) {}

/// Construct an ArrayRef from a std::array
template <size_t N>
Expand Down Expand Up @@ -123,32 +124,6 @@ namespace llvm {
#pragma GCC diagnostic pop
#endif

/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
/// ensure that only ArrayRefs of pointers can be converted.
template <typename U>
ArrayRef(const ArrayRef<U *> &A,
std::enable_if_t<std::is_convertible<U *const *, T const *>::value>
* = nullptr)
: Data(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,
std::enable_if_t<std::is_convertible<U *const *, T const *>::value> * =
nullptr)
: 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,
std::enable_if_t<std::is_convertible<U *const *, T const *>::value>
* = nullptr)
: Data(Vec.data()), Length(Vec.size()) {}

/// Construct an ArrayRef<T> from iterator_range<U*>. This uses SFINAE
/// to ensure that this is only used for iterator ranges over plain pointer
/// iterators.
Expand Down
19 changes: 18 additions & 1 deletion llvm/unittests/ADT/ArrayRefTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@

#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
#include <limits>
#include <vector>
#if __has_include(<version>)
#include <version>
#endif
#ifdef __cpp_lib_span
#include <span>
#endif

using namespace llvm;

// Check that the ArrayRef-of-pointer converting constructor only allows adding
Expand Down Expand Up @@ -406,4 +412,15 @@ TEST(ArrayRefTest, MutableArrayRefDeductionGuides) {
}
}

#ifdef __cpp_lib_span
static_assert(std::is_constructible_v<ArrayRef<int>, std::span<const int>>,
"should be able to construct ArrayRef from const std::span");
static_assert(std::is_constructible_v<std::span<const int>, ArrayRef<int>>,
"should be able to construct const std::span from ArrayRef");
static_assert(std::is_constructible_v<ArrayRef<int>, std::span<int>>,
"should be able to construct ArrayRef from mutable std::span");
static_assert(!std::is_constructible_v<std::span<int>, ArrayRef<int>>,
"cannot construct mutable std::span from ArrayRef");
#endif

} // end anonymous namespace
Loading