Added from-container constructors.

This commit is contained in:
Neil MacIntosh 2016-03-01 12:11:41 -08:00
parent f61a9bba48
commit c40094a532
5 changed files with 68 additions and 34 deletions

View File

@ -1156,22 +1156,22 @@ namespace details
}; };
template <typename T> template <typename T>
struct is_span_oracle : std::false_type struct is_multi_span_oracle : std::false_type
{ {
}; };
template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions> template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
struct is_span_oracle<multi_span<ValueType, FirstDimension, RestDimensions...>> : std::true_type struct is_multi_span_oracle<multi_span<ValueType, FirstDimension, RestDimensions...>> : std::true_type
{ {
}; };
template <typename ValueType, std::ptrdiff_t Rank> template <typename ValueType, std::ptrdiff_t Rank>
struct is_span_oracle<strided_span<ValueType, Rank>> : std::true_type struct is_multi_span_oracle<strided_span<ValueType, Rank>> : std::true_type
{ {
}; };
template <typename T> template <typename T>
struct is_span : is_span_oracle<std::remove_cv_t<T>> struct is_multi_span : is_multi_span_oracle<std::remove_cv_t<T>>
{ {
}; };
} }
@ -1324,7 +1324,7 @@ public:
// type-requirements: container must have .size(), operator[] which are value_type compatible // type-requirements: container must have .size(), operator[] which are value_type compatible
template <typename Cont, typename DataType = typename Cont::value_type, template <typename Cont, typename DataType = typename Cont::value_type,
typename = std::enable_if_t< typename = std::enable_if_t<
!details::is_span<Cont>::value && !details::is_multi_span<Cont>::value &&
std::is_convertible<DataType (*)[], value_type (*)[]>::value && std::is_convertible<DataType (*)[], value_type (*)[]>::value &&
std::is_same<std::decay_t<decltype(std::declval<Cont>().size(), std::is_same<std::decay_t<decltype(std::declval<Cont>().size(),
*std::declval<Cont>().data())>, *std::declval<Cont>().data())>,
@ -1338,7 +1338,7 @@ public:
// prevent constructing from temporary containers // prevent constructing from temporary containers
template <typename Cont, typename DataType = typename Cont::value_type, template <typename Cont, typename DataType = typename Cont::value_type,
typename = std::enable_if_t< typename = std::enable_if_t<
!details::is_span<Cont>::value && !details::is_multi_span<Cont>::value &&
std::is_convertible<DataType (*)[], value_type (*)[]>::value && std::is_convertible<DataType (*)[], value_type (*)[]>::value &&
std::is_same<std::decay_t<decltype(std::declval<Cont>().size(), std::is_same<std::decay_t<decltype(std::declval<Cont>().size(),
*std::declval<Cont>().data())>, *std::declval<Cont>().data())>,
@ -1595,7 +1595,7 @@ template <typename SpanType, typename... Dimensions2, size_t DimCount = sizeof..
constexpr multi_span<typename SpanType::value_type, Dimensions2::value...> as_span(SpanType s, constexpr multi_span<typename SpanType::value_type, Dimensions2::value...> as_span(SpanType s,
Dimensions2... dims) Dimensions2... dims)
{ {
static_assert(details::is_span<SpanType>::value, static_assert(details::is_multi_span<SpanType>::value,
"Variadic as_span() is for reshaping existing spans."); "Variadic as_span() is for reshaping existing spans.");
using BoundsType = using BoundsType =
typename multi_span<typename SpanType::value_type, (Dimensions2::value)...>::bounds_type; typename multi_span<typename SpanType::value_type, (Dimensions2::value)...>::bounds_type;
@ -1718,7 +1718,7 @@ constexpr multi_span<T, dynamic_range> as_span(T* begin, T* end)
template <typename Cont> template <typename Cont>
constexpr auto as_span(Cont& arr) -> std::enable_if_t< constexpr auto as_span(Cont& arr) -> std::enable_if_t<
!details::is_span<std::decay_t<Cont>>::value, !details::is_multi_span<std::decay_t<Cont>>::value,
multi_span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>> multi_span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>>
{ {
Expects(arr.size() < PTRDIFF_MAX); Expects(arr.size() < PTRDIFF_MAX);
@ -1727,7 +1727,7 @@ constexpr auto as_span(Cont& arr) -> std::enable_if_t<
template <typename Cont> template <typename Cont>
constexpr auto as_span(Cont&& arr) -> std::enable_if_t< constexpr auto as_span(Cont&& arr) -> std::enable_if_t<
!details::is_span<std::decay_t<Cont>>::value, !details::is_multi_span<std::decay_t<Cont>>::value,
multi_span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>> = delete; multi_span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>> = delete;
// from basic_string which doesn't have nonconst .data() member like other contiguous containers // from basic_string which doesn't have nonconst .data() member like other contiguous containers

View File

@ -72,12 +72,35 @@
namespace gsl namespace gsl
{ {
template <class ElementType, std::ptrdiff_t Extent = dynamic_extent>
class span;
namespace details
{
template <class T>
struct is_span_oracle : std::false_type
{
};
template <class ElementType, std::ptrdiff_t Extent>
struct is_span_oracle<gsl::span<ElementType, Extent>> : std::true_type
{
};
template <class T>
struct is_span : is_span_oracle<std::remove_cv_t<T>>
{
};
} // namespace details
// [views.constants], constants // [views.constants], constants
constexpr const std::ptrdiff_t dynamic_extent = -1; constexpr const std::ptrdiff_t dynamic_extent = -1;
// [span], class template span // [span], class template span
template <class ElementType, std::ptrdiff_t Extent = dynamic_extent> template <class ElementType, std::ptrdiff_t Extent>
class span { class span {
public: public:
// constants and types // constants and types
@ -122,11 +145,25 @@ public:
: storage_(&arr[0], extent_type<N>()) : storage_(&arr[0], extent_type<N>())
{} {}
#if 0 // TODO // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement
template <class Container> // on Container to be a contiguous sequence container.
constexpr span(Container& cont); template <class Container,
template <class Container> class = std::enable_if_t<!details::is_span<Container>::value &&
std::is_convertible<Container::pointer, pointer>::value &&
std::is_convertible<Container::pointer, decltype(std::declval<Container>().data())>::value>
>
constexpr span(Container& cont) : span(cont.data(), cont.size()) {}
// NB: the SFINAE here uses .data() as an incomplete/imperfect proxy for the requirement
// on Container to be a contiguous sequence container.
template <class Container,
class = std::enable_if_t<!details::is_span<Container>::value &&
std::is_convertible<Container::pointer, pointer>::value &&
std::is_convertible<Container::pointer, decltype(std::declval<Container>().data())>::value>
>
span(const Container&&) = delete; span(const Container&&) = delete;
#if 0 // TODO
constexpr span(const span& other) noexcept = default; constexpr span(const span& other) noexcept = default;
constexpr span(span&& other) noexcept = default; constexpr span(span&& other) noexcept = default;
template <class OtherElementType, ptrdiff_t OtherExtent> template <class OtherElementType, ptrdiff_t OtherExtent>
@ -231,9 +268,6 @@ private:
storage_type(pointer data, OtherExtentType ext) storage_type(pointer data, OtherExtentType ext)
: ExtentType(ext), data_(data) {} : ExtentType(ext), data_(data) {}
//storage_type(pointer data, ExtentType ext)
// : ExtentType(ext), data_(data) {}
constexpr inline pointer data() const noexcept constexpr inline pointer data() const noexcept
{ return data_; } { return data_; }

View File

@ -297,7 +297,7 @@ public:
// from containers. Containers must have .size() and .data() function signatures // from containers. Containers must have .size() and .data() function signatures
template <typename Cont, typename DataType = typename Cont::value_type, template <typename Cont, typename DataType = typename Cont::value_type,
typename Dummy = std::enable_if_t<!details::is_span<Cont>::value typename Dummy = std::enable_if_t<!details::is_multi_span<Cont>::value
&& !details::is_basic_string_span<Cont>::value && !details::is_basic_string_span<Cont>::value
&& !(!std::is_const<value_type>::value && std::is_const<Cont>::value) // no converting const containers to non-const span && !(!std::is_const<value_type>::value && std::is_const<Cont>::value) // no converting const containers to non-const span
&& std::is_convertible<DataType*, value_type*>::value && std::is_convertible<DataType*, value_type*>::value
@ -309,7 +309,7 @@ public:
// disallow creation from temporary containers and strings // disallow creation from temporary containers and strings
template <typename Cont, typename DataType = typename Cont::value_type, template <typename Cont, typename DataType = typename Cont::value_type,
typename Dummy = std::enable_if_t<!details::is_span<Cont>::value typename Dummy = std::enable_if_t<!details::is_multi_span<Cont>::value
&& !details::is_basic_string_span<Cont>::value && !details::is_basic_string_span<Cont>::value
&& std::is_convertible<DataType*, value_type*>::value && std::is_convertible<DataType*, value_type*>::value
&& std::is_same<std::decay_t<decltype(std::declval<Cont>().size(), *std::declval<Cont>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<Cont>().size(), *std::declval<Cont>().data())>, DataType>::value>
@ -640,7 +640,7 @@ bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -654,7 +654,7 @@ bool operator==(gsl::basic_string_span<CharT, Extent> one, const T& other) noexc
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -694,7 +694,7 @@ bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -707,7 +707,7 @@ bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexc
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -748,7 +748,7 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -762,7 +762,7 @@ bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) noexce
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -802,7 +802,7 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -815,7 +815,7 @@ bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexc
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -854,7 +854,7 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -867,7 +867,7 @@ bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) noexce
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -906,7 +906,7 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
@ -919,7 +919,7 @@ bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexc
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_range, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_multi_span<T>::value
&& !gsl::details::is_basic_string_span<T>::value && !gsl::details::is_basic_string_span<T>::value
&& std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>

View File

@ -438,7 +438,7 @@ SUITE(span_tests)
} }
#endif #endif
} }
#if 0
TEST(from_container_constructor) TEST(from_container_constructor)
{ {
std::vector<int> v = {1, 2, 3}; std::vector<int> v = {1, 2, 3};
@ -512,7 +512,7 @@ SUITE(span_tests)
#endif #endif
} }
} }
#if 0
TEST(from_convertible_span_constructor) TEST(from_convertible_span_constructor)
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS

View File

@ -46,7 +46,7 @@ SUITE(string_span_tests)
TEST(TestConstructFromStdVector) TEST(TestConstructFromStdVector)
{ {
std::vector<char> vec(5, 'h'); std::vector<char> vec(5, 'h');
string_span<> v = vec; string_span<> v {vec};
CHECK(v.length() == static_cast<string_span<>::size_type>(vec.size())); CHECK(v.length() == static_cast<string_span<>::size_type>(vec.size()));
} }