Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Enable construction of vectors from std::initializer_list #1836

Merged
merged 3 commits into from
Feb 21, 2023
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
27 changes: 27 additions & 0 deletions testing/vector.cu
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <thrust/sequence.h>
#include <thrust/device_malloc_allocator.h>

#if THRUST_CPP_DIALECT >= 2011
#include <initializer_list>
#endif
#include <vector>
#include <list>
#include <limits>
Expand Down Expand Up @@ -37,6 +40,30 @@ void TestVectorBool(void)
}
DECLARE_UNITTEST(TestVectorBool);

template <class Vector>
void TestVectorInitializerList(void)
miscco marked this conversation as resolved.
Show resolved Hide resolved
{
Vector v{1, 2, 3};
ASSERT_EQUAL(v.size(), 3lu);
ASSERT_EQUAL(v[0], 1);
ASSERT_EQUAL(v[1], 2);
ASSERT_EQUAL(v[2], 3);

v = {1, 2, 3, 4};
ASSERT_EQUAL(v.size(), 4lu);
ASSERT_EQUAL(v[0], 1);
ASSERT_EQUAL(v[1], 2);
ASSERT_EQUAL(v[2], 3);
ASSERT_EQUAL(v[3], 4);

const auto alloc = v.get_allocator();
Vector v2{{1, 2, 3}, alloc};
ASSERT_EQUAL(v2.size(), 3lu);
ASSERT_EQUAL(v2[0], 1);
ASSERT_EQUAL(v2[1], 2);
ASSERT_EQUAL(v2[2], 3);
}
DECLARE_VECTOR_UNITTEST(TestVectorInitializerList);

template <class Vector>
void TestVectorFrontBack(void)
Expand Down
20 changes: 18 additions & 2 deletions thrust/detail/vector_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <thrust/detail/type_traits.h>
#include <thrust/detail/config.h>
#include <thrust/detail/contiguous_storage.h>

#include <initializer_list>
#include <vector>

THRUST_NAMESPACE_BEGIN
Expand Down Expand Up @@ -123,12 +125,26 @@ template<typename T, typename Alloc>
*/
vector_base &operator=(const vector_base &v);

#if THRUST_CPP_DIALECT >= 2011
/*! Move assign operator moves from another vector_base.
* \param v The vector_base to move.
*/
vector_base &operator=(vector_base &&v);
#endif

/*! This constructor builds a \p vector_base from an intializer_list.
* \param il The intializer_list.
*/
vector_base(std::initializer_list<T> il);

/*! This constructor builds a \p vector_base from an intializer_list.
* \param il The intializer_list.
* \param alloc The allocator to use by this device_vector.
*/
vector_base(std::initializer_list<T> il, const Alloc &alloc);

/*! Assign operator copies from an initializer_list
* \param il The initializer_list.
*/
vector_base &operator=(std::initializer_list<T> il);

/*! Copy constructor copies from an exemplar vector_base with different
* type.
Expand Down
28 changes: 28 additions & 0 deletions thrust/detail/vector_base.inl
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,34 @@ template<typename T, typename Alloc>
return *this;
} // end vector_base::operator=()

template<typename T, typename Alloc>
vector_base<T,Alloc>
::vector_base(std::initializer_list<T> il)
:m_storage(),
m_size(0)
{
range_init(il.begin(), il.end());
} // end vector_base::vector_base()
Comment on lines +198 to +205
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm lazy, so I'm always a fan of delegating to other constructors when possible. In this case, we can delegate to the iterator pair ctor:

::vector_base(InputIterator first,

Suggested change
template<typename T, typename Alloc>
vector_base<T,Alloc>
::vector_base(std::initializer_list<T> il)
:m_storage(),
m_size(0)
{
range_init(il.begin(), il.end());
} // end vector_base::vector_base()
template<typename T, typename Alloc>
vector_base<T,Alloc>
::vector_base(std::initializer_list<T> il) : vector_base(std::cbegin(il), std::cend(il)) {}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did not touch those constructors and we should either move all of them to a consistent pattern or leave them as is.


template<typename T, typename Alloc>
vector_base<T,Alloc>
::vector_base(std::initializer_list<T> il, const Alloc &alloc)
:m_storage(alloc),
m_size(0)
{
range_init(il.begin(), il.end());
} // end vector_base::vector_base()

template<typename T, typename Alloc>
vector_base<T,Alloc> &
vector_base<T,Alloc>
::operator=(std::initializer_list<T> il)
{
assign(il.begin(), il.end());

return *this;
} // end vector_base::operator=()

template<typename T, typename Alloc>
template<typename IteratorOrIntegralType>
void vector_base<T,Alloc>
Expand Down
20 changes: 20 additions & 0 deletions thrust/device_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <thrust/detail/vector_base.h>
#include <thrust/device_allocator.h>

#include <initializer_list>
#include <vector>
#include <utility>

Expand Down Expand Up @@ -197,6 +198,25 @@ template<typename T, typename Alloc = thrust::device_allocator<T> >
device_vector &operator=(const detail::vector_base<OtherT,OtherAlloc> &v)
{ Parent::operator=(v); return *this; }

/*! This constructor builds a \p device_vector from an intializer_list.
* \param il The intializer_list.
*/
device_vector(std::initializer_list<T> il)
:Parent(il) {}

/*! This constructor builds a \p device_vector from an intializer_list.
* \param il The intializer_list.
* \param alloc The allocator to use by this device_vector.
*/
device_vector(std::initializer_list<T> il, const Alloc &alloc)
:Parent(il, alloc) {}

/*! Assign an \p intializer_list with a matching element type
* \param il The intializer_list.
*/
device_vector &operator=(std::initializer_list<T> il)
{ Parent::operator=(il); return *this; }

/*! This constructor builds a \p device_vector from a range.
* \param first The beginning of the range.
* \param last The end of the range.
Expand Down
21 changes: 21 additions & 0 deletions thrust/host_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <thrust/detail/config.h>
#include <thrust/detail/memory_wrapper.h>
#include <thrust/detail/vector_base.h>

#include <initializer_list>
#include <vector>
#include <utility>

Expand Down Expand Up @@ -216,6 +218,25 @@ template<typename T, typename Alloc = std::allocator<T> >
__host__
host_vector &operator=(const detail::vector_base<OtherT,OtherAlloc> &v)
{ Parent::operator=(v); return *this; }

/*! This constructor builds a \p host_vector from an intializer_list.
* \param il The intializer_list.
*/
host_vector(std::initializer_list<T> il)
:Parent(il) {}

/*! This constructor builds a \p host_vector from an intializer_list.
* \param il The intializer_list.
* \param alloc The allocator to use by this host_vector.
*/
host_vector(std::initializer_list<T> il, const Alloc &alloc)
:Parent(il, alloc) {}

/*! Assign an \p intializer_list with a matching element type
* \param il The intializer_list.
*/
host_vector &operator=(std::initializer_list<T> il)
{ Parent::operator=(il); return *this; }

/*! This constructor builds a \p host_vector from a range.
* \param first The beginning of the range.
Expand Down
21 changes: 21 additions & 0 deletions thrust/system/cpp/detail/vector.inl
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,27 @@ template<typename T, typename Allocator>
return *this;
}
#endif

template<typename T, typename Allocator>
vector<T,Allocator>
::vector(std::initializer_list<T> il)
: super_t(il)
{}

template<typename T, typename Allocator>
vector<T,Allocator>
::vector(std::initializer_list<T> il, const Allocator& alloc)
: super_t(il, alloc)
{}

template<typename T, typename Allocator>
vector<T,Allocator> &
vector<T,Allocator>
::operator=(std::initializer_list<T> il)
{
super_t::operator=(il);
return *this;
}

template<typename T, typename Allocator>
template<typename OtherT, typename OtherAllocator>
Expand Down