[ADT] Make iterable SmallVector template overrides more specific

Summary:
This prevents the iterator overrides from being selected in
the case where non-iterator types are used as arguments, which
is of particular importance in cases where other overrides with
identical types exist.

Reviewers: dblaikie, bkramer, rafael

Subscribers: llvm-commits, efriedma

Differential Revision: https://reviews.llvm.org/D33919

llvm-svn: 305105
This commit is contained in:
Francis Ricci 2017-06-09 20:31:53 +00:00
parent f21b803876
commit e22b696936
2 changed files with 78 additions and 4 deletions

View File

@ -388,7 +388,10 @@ public:
void swap(SmallVectorImpl &RHS);
/// Add the specified range to the end of the SmallVector.
template<typename in_iter>
template <typename in_iter,
typename = typename std::enable_if<std::is_convertible<
typename std::iterator_traits<in_iter>::iterator_category,
std::input_iterator_tag>::value>::type>
void append(in_iter in_start, in_iter in_end) {
size_type NumInputs = std::distance(in_start, in_end);
// Grow allocated space if needed.
@ -426,7 +429,11 @@ public:
std::uninitialized_fill(this->begin(), this->end(), Elt);
}
template <typename in_iter> void assign(in_iter in_start, in_iter in_end) {
template <typename in_iter,
typename = typename std::enable_if<std::is_convertible<
typename std::iterator_traits<in_iter>::iterator_category,
std::input_iterator_tag>::value>::type>
void assign(in_iter in_start, in_iter in_end) {
clear();
append(in_start, in_end);
}
@ -579,7 +586,10 @@ public:
return I;
}
template<typename ItTy>
template <typename ItTy,
typename = typename std::enable_if<std::is_convertible<
typename std::iterator_traits<ItTy>::iterator_category,
std::input_iterator_tag>::value>::type>
iterator insert(iterator I, ItTy From, ItTy To) {
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
size_t InsertElt = I - this->begin();
@ -860,7 +870,10 @@ public:
this->assign(Size, Value);
}
template<typename ItTy>
template <typename ItTy,
typename = typename std::enable_if<std::is_convertible<
typename std::iterator_traits<ItTy>::iterator_category,
std::input_iterator_tag>::value>::type>
SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
this->append(S, E);
}

View File

@ -209,6 +209,22 @@ typedef ::testing::Types<SmallVector<Constructable, 0>,
> SmallVectorTestTypes;
TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes);
// Constructor test.
TYPED_TEST(SmallVectorTest, ConstructorNonIterTest) {
SCOPED_TRACE("ConstructorTest");
this->theVector = SmallVector<Constructable, 2>(2, 2);
this->assertValuesInOrder(this->theVector, 2u, 2, 2);
}
// Constructor test.
TYPED_TEST(SmallVectorTest, ConstructorIterTest) {
SCOPED_TRACE("ConstructorTest");
int arr[] = {1, 2, 3};
this->theVector =
SmallVector<Constructable, 4>(std::begin(arr), std::end(arr));
this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
}
// New vector test.
TYPED_TEST(SmallVectorTest, EmptyVectorTest) {
SCOPED_TRACE("EmptyVectorTest");
@ -415,6 +431,33 @@ TYPED_TEST(SmallVectorTest, AppendRepeatedTest) {
this->assertValuesInOrder(this->theVector, 3u, 1, 77, 77);
}
// Append test
TYPED_TEST(SmallVectorTest, AppendNonIterTest) {
SCOPED_TRACE("AppendRepeatedTest");
this->theVector.push_back(Constructable(1));
this->theVector.append(2, 7);
this->assertValuesInOrder(this->theVector, 3u, 1, 7, 7);
}
TYPED_TEST(SmallVectorTest, AppendRepeatedNonForwardIterator) {
SCOPED_TRACE("AppendRepeatedTest");
struct output_iterator {
typedef std::output_iterator_tag iterator_category;
typedef int value_type;
typedef int difference_type;
typedef value_type *pointer;
typedef value_type &reference;
operator int() { return 2; }
operator Constructable() { return 7; }
};
this->theVector.push_back(Constructable(1));
this->theVector.append(output_iterator(), output_iterator());
this->assertValuesInOrder(this->theVector, 3u, 1, 7, 7);
}
// Assign test
TYPED_TEST(SmallVectorTest, AssignTest) {
SCOPED_TRACE("AssignTest");
@ -434,6 +477,15 @@ TYPED_TEST(SmallVectorTest, AssignRangeTest) {
this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
}
// Assign test
TYPED_TEST(SmallVectorTest, AssignNonIterTest) {
SCOPED_TRACE("AssignTest");
this->theVector.push_back(Constructable(1));
this->theVector.assign(2, 7);
this->assertValuesInOrder(this->theVector, 2u, 7, 7);
}
// Move-assign test
TYPED_TEST(SmallVectorTest, MoveAssignTest) {
SCOPED_TRACE("MoveAssignTest");
@ -532,6 +584,15 @@ TYPED_TEST(SmallVectorTest, InsertRepeatedTest) {
this->assertValuesInOrder(this->theVector, 6u, 1, 16, 16, 2, 3, 4);
}
TYPED_TEST(SmallVectorTest, InsertRepeatedNonIterTest) {
SCOPED_TRACE("InsertRepeatedTest");
this->makeSequence(this->theVector, 1, 4);
Constructable::reset();
auto I = this->theVector.insert(this->theVector.begin() + 1, 2, 7);
EXPECT_EQ(this->theVector.begin() + 1, I);
this->assertValuesInOrder(this->theVector, 6u, 1, 7, 7, 2, 3, 4);
}
TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) {
SCOPED_TRACE("InsertRepeatedTest");