Reformat files to follow clang-format style

Project files were not following the clang-format style. For people
using IDEs were clang-format is always run after a save this would
cause unwanted changes.

This commit only applies "clang-format -i" to files.
This commit is contained in:
Tiago Macarios 2017-04-17 17:35:40 -07:00
parent c5851a8161
commit 8faa661d42
20 changed files with 1965 additions and 1892 deletions

View File

@ -24,24 +24,25 @@
#include <gsl/multi_span> // multi_span, strided_span... #include <gsl/multi_span> // multi_span, strided_span...
#include <gsl/span> // span #include <gsl/span> // span
#include <gsl/string_span> // zstring, string_span, zstring_builder... #include <gsl/string_span> // zstring, string_span, zstring_builder...
#include <memory>
#include <iostream> #include <iostream>
#include <memory>
#if defined(_MSC_VER) && _MSC_VER < 1910 #if defined(_MSC_VER) && _MSC_VER < 1910
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr /*constexpr*/ #define constexpr /*constexpr*/
// MSVC 2013 workarounds // MSVC 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
// noexcept is not understood // noexcept is not understood
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept /*noexcept*/ #define noexcept /*noexcept*/
// turn off some misguided warnings // turn off some misguided warnings
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior #pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // defined(_MSC_VER) && _MSC_VER < 1910 #endif // defined(_MSC_VER) && _MSC_VER < 1910
namespace gsl namespace gsl
{ {
@ -76,10 +77,15 @@ public:
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr."); static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>> template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(U&& u) : ptr_(std::forward<U>(u)) { Expects(ptr_ != nullptr); } constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
{
Expects(ptr_ != nullptr);
}
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>> template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(const not_null<U>& other) : not_null(other.get()) {} constexpr not_null(const not_null<U>& other) : not_null(other.get())
{
}
not_null(const not_null& other) = default; not_null(const not_null& other) = default;
not_null& operator=(const not_null& other) = default; not_null& operator=(const not_null& other) = default;
@ -157,7 +163,7 @@ auto operator>=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.
template <class T, class U> template <class T, class U>
std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete; std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete;
template <class T> template <class T>
not_null<T> operator-(const not_null<T>&, std::ptrdiff_t) = delete; not_null<T> operator-(const not_null<T>&, std::ptrdiff_t) = delete;
template <class T> template <class T>
not_null<T> operator+(const not_null<T>&, std::ptrdiff_t) = delete; not_null<T> operator+(const not_null<T>&, std::ptrdiff_t) = delete;
template <class T> template <class T>
@ -176,15 +182,15 @@ struct hash<gsl::not_null<T>>
} // namespace std } // namespace std
#if defined(_MSC_VER) && _MSC_VER < 1910 #if defined(_MSC_VER) && _MSC_VER < 1910
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#undef noexcept #undef noexcept
#pragma pop_macro("noexcept") #pragma pop_macro("noexcept")
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // defined(_MSC_VER) && _MSC_VER < 1910 #endif // defined(_MSC_VER) && _MSC_VER < 1910
#endif // GSL_GSL_H #endif // GSL_GSL_H

View File

@ -20,30 +20,32 @@
#define GSL_ALGORITHM_H #define GSL_ALGORITHM_H
#include <gsl/span> #include <gsl/span>
#include <algorithm> #include <algorithm>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
// turn off some warnings that are noisy about our Expects statements // turn off some warnings that are noisy about our Expects statements
#pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4127) // conditional expression is constant
// blanket turn off warnings from CppCoreCheck for now // blanket turn off warnings from CppCoreCheck for now
// so people aren't annoyed by them when running the tool. // so people aren't annoyed by them when running the tool.
// more targeted suppressions will be added in a future update to the GSL // more targeted suppressions will be added in a future update to the GSL
#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495) #pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
#endif // _MSC_VER #endif // _MSC_VER
namespace gsl namespace gsl
{ {
template <class SrcElementType, std::ptrdiff_t SrcExtent, template <class SrcElementType, std::ptrdiff_t SrcExtent, class DestElementType,
class DestElementType, std::ptrdiff_t DestExtent> std::ptrdiff_t DestExtent>
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest) void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
{ {
static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value, static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value,
"Elements of source span can not be assigned to elements of destination span"); "Elements of source span can not be assigned to elements of destination span");
static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent || (SrcExtent <= DestExtent), static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
(SrcExtent <= DestExtent),
"Source range is longer than target range"); "Source range is longer than target range");
Expects(dest.size() >= src.size()); Expects(dest.size() >= src.size());
@ -53,7 +55,7 @@ void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent>
} // namespace gsl } // namespace gsl
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER #endif // _MSC_VER
#endif // GSL_ALGORITHM_H #endif // GSL_ALGORITHM_H

View File

@ -32,18 +32,18 @@
// //
#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) || defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) || \ #if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) || defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) || \
defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)) defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
#define GSL_TERMINATE_ON_CONTRACT_VIOLATION #define GSL_TERMINATE_ON_CONTRACT_VIOLATION
#endif #endif
#define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
#if defined(__clang__) || defined(__GNUC__) #if defined(__clang__) || defined(__GNUC__)
#define GSL_LIKELY(x) __builtin_expect (!!(x), 1) #define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
#define GSL_UNLIKELY(x) __builtin_expect (!!(x), 0) #define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else #else
#define GSL_LIKELY(x) (!!(x)) #define GSL_LIKELY(x) (!!(x))
#define GSL_UNLIKELY(x) (!!(x)) #define GSL_UNLIKELY(x) (!!(x))
#endif #endif
// //
@ -53,13 +53,13 @@
// whether or not cond is actually evaluated. // whether or not cond is actually evaluated.
// //
#ifdef _MSC_VER #ifdef _MSC_VER
#define GSL_ASSUME(cond) __assume(cond) #define GSL_ASSUME(cond) __assume(cond)
#elif defined(__clang__) #elif defined(__clang__)
#define GSL_ASSUME(cond) __builtin_assume(cond) #define GSL_ASSUME(cond) __builtin_assume(cond)
#elif defined(__GNUC__) #elif defined(__GNUC__)
#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable()) #define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable())
#else #else
#define GSL_ASSUME(cond) static_cast<void>(!!(cond)) #define GSL_ASSUME(cond) static_cast<void>(!!(cond))
#endif #endif
// //
@ -76,18 +76,18 @@ struct fail_fast : public std::logic_error
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION) #if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) \ #define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : \ (GSL_LIKELY(cond) ? static_cast<void>(0) \
throw gsl::fail_fast("GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__))) : throw gsl::fail_fast("GSL: " type " failure at " __FILE__ \
": " GSL_STRINGIFY(__LINE__)))
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) #elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) \ #define GSL_CONTRACT_CHECK(type, cond) (GSL_LIKELY(cond) ? static_cast<void>(0) : std::terminate())
(GSL_LIKELY(cond) ? static_cast<void>(0) : std::terminate())
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) #elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond) #define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)
#endif #endif

View File

@ -22,22 +22,22 @@
#include <type_traits> #include <type_traits>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
// don't warn about function style casts in byte related operators // don't warn about function style casts in byte related operators
#pragma warning(disable : 26493) #pragma warning(disable : 26493)
// MSVC 2013 workarounds // MSVC 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
// constexpr is not understood // constexpr is not understood
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr /*constexpr*/ #define constexpr /*constexpr*/
// noexcept is not understood // noexcept is not understood
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept /*noexcept*/ #define noexcept /*noexcept*/
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // _MSC_VER #endif // _MSC_VER
namespace gsl namespace gsl
{ {
@ -109,47 +109,46 @@ inline constexpr IntegerType to_integer(byte b) noexcept
return static_cast<IntegerType>(b); return static_cast<IntegerType>(b);
} }
template<bool E, typename T> template <bool E, typename T>
inline constexpr byte to_byte_impl(T t) noexcept inline constexpr byte to_byte_impl(T t) noexcept
{ {
static_assert( static_assert(
E, E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
"gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " "If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version.");
"If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version."
);
return static_cast<byte>(t); return static_cast<byte>(t);
} }
template<> template <>
inline constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept inline constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
{ {
return byte(t); return byte(t);
} }
template<typename T> template <typename T>
inline constexpr byte to_byte(T t) noexcept inline constexpr byte to_byte(T t) noexcept
{ {
return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t); return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
} }
template <int I> template <int I>
inline constexpr byte to_byte() noexcept inline constexpr byte to_byte() noexcept
{ {
static_assert(I >= 0 && I <= 255, "gsl::byte only has 8 bits of storage, values must be in range 0-255"); static_assert(I >= 0 && I <= 255,
"gsl::byte only has 8 bits of storage, values must be in range 0-255");
return static_cast<byte>(I); return static_cast<byte>(I);
} }
} // namespace gsl } // namespace gsl
#ifdef _MSC_VER #ifdef _MSC_VER
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
#undef noexcept #undef noexcept
#pragma pop_macro("noexcept") #pragma pop_macro("noexcept")
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER #endif // _MSC_VER
#endif // GSL_BYTE_H #endif // GSL_BYTE_H

View File

@ -20,28 +20,29 @@
#define GSL_UTIL_H #define GSL_UTIL_H
#include <gsl/gsl_assert> // Ensures/Expects #include <gsl/gsl_assert> // Ensures/Expects
#include <array> #include <array>
#include <exception> #include <exception>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4127) // conditional expression is constant
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr /*constexpr*/ #define constexpr /*constexpr*/
// MSVC 2013 workarounds // MSVC 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
// noexcept is not understood // noexcept is not understood
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept /*noexcept*/ #define noexcept /*noexcept*/
// turn off some misguided warnings // turn off some misguided warnings
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior #pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#endif // _MSC_VER #endif // _MSC_VER
namespace gsl namespace gsl
{ {
@ -154,16 +155,16 @@ inline constexpr T at(const std::initializer_list<T> cont, const std::ptrdiff_t
} // namespace gsl } // namespace gsl
#if defined(_MSC_VER) #if defined(_MSC_VER)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#undef noexcept #undef noexcept
#pragma pop_macro("noexcept") #pragma pop_macro("noexcept")
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER #endif // _MSC_VER
#endif // GSL_UTIL_H #endif // GSL_UTIL_H

View File

@ -22,6 +22,7 @@
#include <gsl/gsl_assert> #include <gsl/gsl_assert>
#include <gsl/gsl_byte> #include <gsl/gsl_byte>
#include <gsl/gsl_util> #include <gsl/gsl_util>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cassert> #include <cassert>
@ -37,34 +38,34 @@
#include <utility> #include <utility>
#ifdef _MSC_VER #ifdef _MSC_VER
// turn off some warnings that are noisy about our Expects statements // turn off some warnings that are noisy about our Expects statements
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4127) // conditional expression is constant
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr /*constexpr*/ #define constexpr /*constexpr*/
// VS 2013 workarounds // VS 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#define GSL_MSVC_HAS_VARIADIC_CTOR_BUG #define GSL_MSVC_HAS_VARIADIC_CTOR_BUG
#define GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT #define GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT
// noexcept is not understood // noexcept is not understood
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept /*noexcept*/ #define noexcept /*noexcept*/
// turn off some misguided warnings // turn off some misguided warnings
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior #pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
#pragma warning(disable : 4512) // warns that assignment op could not be generated #pragma warning(disable : 4512) // warns that assignment op could not be generated
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#endif // _MSC_VER #endif // _MSC_VER
#ifdef GSL_THROW_ON_CONTRACT_VIOLATION #ifdef GSL_THROW_ON_CONTRACT_VIOLATION
#define GSL_NOEXCEPT /*noexcept*/ #define GSL_NOEXCEPT /*noexcept*/
#else #else
#define GSL_NOEXCEPT noexcept #define GSL_NOEXCEPT noexcept
#endif // GSL_THROW_ON_CONTRACT_VIOLATION #endif // GSL_THROW_ON_CONTRACT_VIOLATION
namespace gsl namespace gsl
@ -207,7 +208,10 @@ public:
return ret; return ret;
} }
friend constexpr index operator*(value_type v, const index& rhs) GSL_NOEXCEPT { return rhs * v; } friend constexpr index operator*(value_type v, const index& rhs) GSL_NOEXCEPT
{
return rhs * v;
}
constexpr index& operator*=(value_type v) GSL_NOEXCEPT constexpr index& operator*=(value_type v) GSL_NOEXCEPT
{ {
@ -344,10 +348,11 @@ namespace details
static const std::size_t DynamicNum = Base::DynamicNum + 1; static const std::size_t DynamicNum = Base::DynamicNum + 1;
static const size_type CurrentRange = dynamic_range; static const size_type CurrentRange = dynamic_range;
static const size_type TotalSize = dynamic_range; static const size_type TotalSize = dynamic_range;
private: private:
size_type m_bound; size_type m_bound;
public:
public:
BoundsRanges(const std::ptrdiff_t* const arr) BoundsRanges(const std::ptrdiff_t* const arr)
: Base(arr + 1), m_bound(*arr * this->Base::totalSize()) : Base(arr + 1), m_bound(*arr * this->Base::totalSize())
{ {
@ -492,7 +497,8 @@ namespace details
return obj_; return obj_;
} }
template <std::size_t N, typename MyChain = TypeChain, typename MyBase = typename MyChain::Base> template <std::size_t N, typename MyChain = TypeChain,
typename MyBase = typename MyChain::Base>
auto getObj(std::false_type) auto getObj(std::false_type)
-> decltype(TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>()) -> decltype(TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>())
{ {
@ -690,7 +696,10 @@ public:
return !(*this == rhs); return !(*this == rhs);
} }
constexpr const_iterator begin() const GSL_NOEXCEPT { return const_iterator(*this, index_type{}); } constexpr const_iterator begin() const GSL_NOEXCEPT
{
return const_iterator(*this, index_type{});
}
constexpr const_iterator end() const GSL_NOEXCEPT constexpr const_iterator end() const GSL_NOEXCEPT
{ {
@ -790,9 +799,15 @@ public:
} }
constexpr index_type index_bounds() const GSL_NOEXCEPT { return m_extents; } constexpr index_type index_bounds() const GSL_NOEXCEPT { return m_extents; }
constexpr const_iterator begin() const GSL_NOEXCEPT { return const_iterator{*this, index_type{}}; } constexpr const_iterator begin() const GSL_NOEXCEPT
{
return const_iterator{*this, index_type{}};
}
constexpr const_iterator end() const GSL_NOEXCEPT { return const_iterator{*this, index_bounds()}; } constexpr const_iterator end() const GSL_NOEXCEPT
{
return const_iterator{*this, index_bounds()};
}
private: private:
index_type m_extents; index_type m_extents;
@ -931,18 +946,27 @@ public:
return curr_ == rhs.curr_; return curr_ == rhs.curr_;
} }
constexpr bool operator!=(const bounds_iterator& rhs) const GSL_NOEXCEPT { return !(*this == rhs); } constexpr bool operator!=(const bounds_iterator& rhs) const GSL_NOEXCEPT
{
return !(*this == rhs);
}
constexpr bool operator<(const bounds_iterator& rhs) const GSL_NOEXCEPT constexpr bool operator<(const bounds_iterator& rhs) const GSL_NOEXCEPT
{ {
return less(curr_, rhs.curr_); return less(curr_, rhs.curr_);
} }
constexpr bool operator<=(const bounds_iterator& rhs) const GSL_NOEXCEPT { return !(rhs < *this); } constexpr bool operator<=(const bounds_iterator& rhs) const GSL_NOEXCEPT
{
return !(rhs < *this);
}
constexpr bool operator>(const bounds_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; } constexpr bool operator>(const bounds_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; }
constexpr bool operator>=(const bounds_iterator& rhs) const GSL_NOEXCEPT { return !(rhs > *this); } constexpr bool operator>=(const bounds_iterator& rhs) const GSL_NOEXCEPT
{
return !(rhs > *this);
}
void swap(bounds_iterator& rhs) GSL_NOEXCEPT void swap(bounds_iterator& rhs) GSL_NOEXCEPT
{ {
@ -1136,7 +1160,7 @@ namespace details
template <typename T, typename Arg, typename... Args> template <typename T, typename Arg, typename... Args>
std::enable_if_t< std::enable_if_t<
!std::is_same<Arg, dim_t<dynamic_range>>::value && !std::is_same<Arg, Sep>::value, T> !std::is_same<Arg, dim_t<dynamic_range>>::value && !std::is_same<Arg, Sep>::value, T>
static_as_multi_span_helper(Arg, Args... args) static_as_multi_span_helper(Arg, Args... args)
{ {
return static_as_multi_span_helper<T>(args...); return static_as_multi_span_helper<T>(args...);
} }
@ -1227,7 +1251,8 @@ public:
// construct from nullptr with size of 0 (helps with template function calls) // construct from nullptr with size of 0 (helps with template function calls)
template <class IntType, typename = std::enable_if_t<std::is_integral<IntType>::value>> template <class IntType, typename = std::enable_if_t<std::is_integral<IntType>::value>>
constexpr multi_span(std::nullptr_t, IntType size) GSL_NOEXCEPT : multi_span(nullptr, bounds_type{}) constexpr multi_span(std::nullptr_t, IntType size) GSL_NOEXCEPT
: multi_span(nullptr, bounds_type{})
{ {
static_assert(bounds_type::dynamic_rank != 0 || static_assert(bounds_type::dynamic_rank != 0 ||
(bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0), (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0),
@ -1249,13 +1274,14 @@ public:
constexpr multi_span(value_type&&) = delete; constexpr multi_span(value_type&&) = delete;
// construct from pointer + length // construct from pointer + length
constexpr multi_span(pointer ptr, size_type size) GSL_NOEXCEPT : multi_span(ptr, bounds_type{size}) constexpr multi_span(pointer ptr, size_type size) GSL_NOEXCEPT
: multi_span(ptr, bounds_type{size})
{ {
} }
// construct from pointer + length - multidimensional // construct from pointer + length - multidimensional
constexpr multi_span(pointer data, bounds_type bounds) GSL_NOEXCEPT : data_(data), constexpr multi_span(pointer data, bounds_type bounds) GSL_NOEXCEPT : data_(data),
bounds_(std::move(bounds)) bounds_(std::move(bounds))
{ {
Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0); Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0);
} }
@ -1426,9 +1452,8 @@ public:
// subspan() - create a subview of count elements starting at offset // subspan() - create a subview of count elements starting at offset
// supplying dynamic_range for count will consume all available elements from offset // supplying dynamic_range for count will consume all available elements from offset
constexpr multi_span<ValueType, dynamic_range> subspan(size_type offset, constexpr multi_span<ValueType, dynamic_range>
size_type count = dynamic_range) const subspan(size_type offset, size_type count = dynamic_range) const GSL_NOEXCEPT
GSL_NOEXCEPT
{ {
Expects((offset >= 0 && offset <= this->size()) && Expects((offset >= 0 && offset <= this->size()) &&
(count == dynamic_range || (count <= this->size() - offset))); (count == dynamic_range || (count <= this->size() - offset)));
@ -1436,8 +1461,8 @@ public:
} }
// section - creates a non-contiguous, strided multi_span from a contiguous one // section - creates a non-contiguous, strided multi_span from a contiguous one
constexpr strided_span<ValueType, Rank> section(index_type origin, index_type extents) const constexpr strided_span<ValueType, Rank> section(index_type origin,
GSL_NOEXCEPT index_type extents) const GSL_NOEXCEPT
{ {
size_type size = this->bounds().total_size() - this->bounds().linearize(origin); size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
return {&this->operator[](origin), size, return {&this->operator[](origin), size,
@ -1451,7 +1476,10 @@ public:
constexpr size_type length() const GSL_NOEXCEPT { return this->size(); } constexpr size_type length() const GSL_NOEXCEPT { return this->size(); }
// length of the multi_span in bytes // length of the multi_span in bytes
constexpr size_type size_bytes() const GSL_NOEXCEPT { return narrow_cast<size_type>(sizeof(value_type)) * this->size(); } constexpr size_type size_bytes() const GSL_NOEXCEPT
{
return narrow_cast<size_type>(sizeof(value_type)) * this->size();
}
// length of the multi_span in bytes // length of the multi_span in bytes
constexpr size_type length_bytes() const GSL_NOEXCEPT { return this->size_bytes(); } constexpr size_type length_bytes() const GSL_NOEXCEPT { return this->size_bytes(); }
@ -1539,8 +1567,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const constexpr bool
GSL_NOEXCEPT operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
{ {
return bounds_.size() == other.bounds_.size() && return bounds_.size() == other.bounds_.size() &&
(data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin())); (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin()));
@ -1549,8 +1577,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const constexpr bool
GSL_NOEXCEPT operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
{ {
return !(*this == other); return !(*this == other);
} }
@ -1558,8 +1586,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const constexpr bool
GSL_NOEXCEPT operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
{ {
return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end());
} }
@ -1567,8 +1595,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const constexpr bool
GSL_NOEXCEPT operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
{ {
return !(other < *this); return !(other < *this);
} }
@ -1576,8 +1604,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const constexpr bool
GSL_NOEXCEPT operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
{ {
return (other < *this); return (other < *this);
} }
@ -1585,8 +1613,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const constexpr bool
GSL_NOEXCEPT operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const GSL_NOEXCEPT
{ {
return !(*this < other); return !(*this < other);
} }
@ -1638,7 +1666,8 @@ multi_span<byte> as_writeable_bytes(multi_span<U, Dimensions...> s) GSL_NOEXCEPT
// on all implementations. It should be considered an experimental extension // on all implementations. It should be considered an experimental extension
// to the standard GSL interface. // to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions> template <typename U, std::ptrdiff_t... Dimensions>
inline constexpr auto as_multi_span(multi_span<const byte, Dimensions...> s) GSL_NOEXCEPT -> multi_span< inline constexpr auto
as_multi_span(multi_span<const byte, Dimensions...> s) GSL_NOEXCEPT -> multi_span<
const U, static_cast<std::ptrdiff_t>( const U, static_cast<std::ptrdiff_t>(
multi_span<const byte, Dimensions...>::bounds_type::static_size != dynamic_range multi_span<const byte, Dimensions...>::bounds_type::static_size != dynamic_range
? (static_cast<std::size_t>( ? (static_cast<std::size_t>(
@ -1830,8 +1859,9 @@ public:
size_type size = this->bounds().total_size() / d; size_type size = this->bounds().total_size() / d;
return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())), return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())),
size, bounds_type{resize_extent(this->bounds().index_bounds(), d), size,
resize_stride(this->bounds().strides(), d)}}; bounds_type{resize_extent(this->bounds().index_bounds(), d),
resize_stride(this->bounds().strides(), d)}};
} }
constexpr strided_span section(index_type origin, index_type extents) const constexpr strided_span section(index_type origin, index_type extents) const
@ -1898,7 +1928,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t OtherRank, template <typename OtherValueType, std::ptrdiff_t OtherRank,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator==(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT constexpr bool
operator==(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
{ {
return bounds_.size() == other.bounds_.size() && return bounds_.size() == other.bounds_.size() &&
(data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin())); (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin()));
@ -1907,7 +1938,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t OtherRank, template <typename OtherValueType, std::ptrdiff_t OtherRank,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator!=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT constexpr bool
operator!=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
{ {
return !(*this == other); return !(*this == other);
} }
@ -1915,7 +1947,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t OtherRank, template <typename OtherValueType, std::ptrdiff_t OtherRank,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator<(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT constexpr bool
operator<(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
{ {
return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end());
} }
@ -1923,7 +1956,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t OtherRank, template <typename OtherValueType, std::ptrdiff_t OtherRank,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator<=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT constexpr bool
operator<=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
{ {
return !(other < *this); return !(other < *this);
} }
@ -1931,7 +1965,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t OtherRank, template <typename OtherValueType, std::ptrdiff_t OtherRank,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator>(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT constexpr bool
operator>(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
{ {
return (other < *this); return (other < *this);
} }
@ -1939,7 +1974,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t OtherRank, template <typename OtherValueType, std::ptrdiff_t OtherRank,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator>=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT constexpr bool
operator>=(const strided_span<OtherValueType, OtherRank>& other) const GSL_NOEXCEPT
{ {
return !(*this < other); return !(*this < other);
} }
@ -2074,15 +2110,24 @@ public:
Expects(m_validator == rhs.m_validator); Expects(m_validator == rhs.m_validator);
return data_ == rhs.data_; return data_ == rhs.data_;
} }
bool operator!=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT { return !(*this == rhs); } bool operator!=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
{
return !(*this == rhs);
}
bool operator<(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT bool operator<(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
{ {
Expects(m_validator == rhs.m_validator); Expects(m_validator == rhs.m_validator);
return data_ < rhs.data_; return data_ < rhs.data_;
} }
bool operator<=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT { return !(rhs < *this); } bool operator<=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
{
return !(rhs < *this);
}
bool operator>(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; } bool operator>(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT { return rhs < *this; }
bool operator>=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT { return !(rhs > *this); } bool operator>=(const contiguous_span_iterator& rhs) const GSL_NOEXCEPT
{
return !(rhs > *this);
}
void swap(contiguous_span_iterator& rhs) GSL_NOEXCEPT void swap(contiguous_span_iterator& rhs) GSL_NOEXCEPT
{ {
std::swap(data_, rhs.data_); std::swap(data_, rhs.data_);
@ -2202,20 +2247,20 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
#undef GSL_NOEXCEPT #undef GSL_NOEXCEPT
#ifdef _MSC_VER #ifdef _MSC_VER
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#undef noexcept #undef noexcept
#pragma pop_macro("noexcept") #pragma pop_macro("noexcept")
#undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG #undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG
#undef GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT #undef GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER #endif // _MSC_VER
#endif // GSL_MULTI_SPAN_H #endif // GSL_MULTI_SPAN_H

View File

@ -23,53 +23,54 @@
#include <gsl/gsl_assert> #include <gsl/gsl_assert>
#include <gsl/gsl_byte> #include <gsl/gsl_byte>
#include <gsl/gsl_util> #include <gsl/gsl_util>
#include <array> #include <array>
#include <iterator> #include <iterator>
#include <limits> #include <limits>
#include <memory>
#include <stdexcept> #include <stdexcept>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <memory>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
// turn off some warnings that are noisy about our Expects statements // turn off some warnings that are noisy about our Expects statements
#pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4127) // conditional expression is constant
// blanket turn off warnings from CppCoreCheck for now // blanket turn off warnings from CppCoreCheck for now
// so people aren't annoyed by them when running the tool. // so people aren't annoyed by them when running the tool.
// more targeted suppressions will be added in a future update to the GSL // more targeted suppressions will be added in a future update to the GSL
#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495) #pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr /*constexpr*/ #define constexpr /*constexpr*/
// VS 2013 workarounds // VS 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#define GSL_MSVC_HAS_VARIADIC_CTOR_BUG #define GSL_MSVC_HAS_VARIADIC_CTOR_BUG
#define GSL_MSVC_NO_DEFAULT_MOVE_CTOR #define GSL_MSVC_NO_DEFAULT_MOVE_CTOR
#define GSL_MSVC_NO_CPP14_STD_EQUAL #define GSL_MSVC_NO_CPP14_STD_EQUAL
// noexcept is not understood // noexcept is not understood
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept /*noexcept*/ #define noexcept /*noexcept*/
#pragma push_macro("alignof") #pragma push_macro("alignof")
#define alignof __alignof #define alignof __alignof
// turn off some misguided warnings // turn off some misguided warnings
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior #pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
#pragma warning(disable : 4512) // warns that assignment op could not be generated #pragma warning(disable : 4512) // warns that assignment op could not be generated
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#endif // _MSC_VER #endif // _MSC_VER
#ifdef GSL_THROW_ON_CONTRACT_VIOLATION #ifdef GSL_THROW_ON_CONTRACT_VIOLATION
#define GSL_NOEXCEPT /*noexcept*/ #define GSL_NOEXCEPT /*noexcept*/
#else #else
#define GSL_NOEXCEPT noexcept #define GSL_NOEXCEPT noexcept
#endif // GSL_THROW_ON_CONTRACT_VIOLATION #endif // GSL_THROW_ON_CONTRACT_VIOLATION
namespace gsl namespace gsl
@ -131,13 +132,13 @@ namespace details
class span_iterator class span_iterator
{ {
using element_type_ = typename Span::element_type; using element_type_ = typename Span::element_type;
public: public:
using iterator_category = std::random_access_iterator_tag; using iterator_category = std::random_access_iterator_tag;
using value_type = std::remove_cv_t<element_type_>; using value_type = std::remove_cv_t<element_type_>;
using difference_type = typename Span::index_type; using difference_type = typename Span::index_type;
using reference = using reference = std::conditional_t<IsConst, const element_type_, element_type_>&;
std::conditional_t<IsConst, const element_type_, element_type_> &;
using pointer = std::add_pointer_t<reference>; using pointer = std::add_pointer_t<reference>;
constexpr span_iterator() GSL_NOEXCEPT : span_iterator(nullptr, 0) {} constexpr span_iterator() GSL_NOEXCEPT : span_iterator(nullptr, 0) {}
@ -154,7 +155,8 @@ namespace details
{ {
} }
constexpr span_iterator<Span, IsConst>& operator=(const span_iterator<Span, IsConst>&) GSL_NOEXCEPT = default; constexpr span_iterator<Span, IsConst>&
operator=(const span_iterator<Span, IsConst>&) GSL_NOEXCEPT = default;
constexpr reference operator*() const constexpr reference operator*() const
{ {
@ -223,7 +225,10 @@ namespace details
return index_ - rhs.index_; return index_ - rhs.index_;
} }
constexpr reference operator[](difference_type n) const GSL_NOEXCEPT { return *(*this + n); } constexpr reference operator[](difference_type n) const GSL_NOEXCEPT
{
return *(*this + n);
}
constexpr friend bool operator==(const span_iterator& lhs, constexpr friend bool operator==(const span_iterator& lhs,
const span_iterator& rhs) GSL_NOEXCEPT const span_iterator& rhs) GSL_NOEXCEPT
@ -249,7 +254,8 @@ namespace details
return !(rhs < lhs); return !(rhs < lhs);
} }
constexpr friend bool operator>(const span_iterator& lhs, const span_iterator& rhs) GSL_NOEXCEPT constexpr friend bool operator>(const span_iterator& lhs,
const span_iterator& rhs) GSL_NOEXCEPT
{ {
return rhs < lhs; return rhs < lhs;
} }
@ -337,7 +343,7 @@ class span
public: public:
// constants and types // constants and types
using element_type = ElementType; using element_type = ElementType;
using value_type = std::remove_cv_t<ElementType>; using value_type = std::remove_cv_t<ElementType>;
using index_type = std::ptrdiff_t; using index_type = std::ptrdiff_t;
using pointer = element_type*; using pointer = element_type*;
using reference = element_type&; using reference = element_type&;
@ -353,10 +359,12 @@ public:
// [span.cons], span constructors, copy, assignment, and destructor // [span.cons], span constructors, copy, assignment, and destructor
template <bool Dependent = false, template <bool Dependent = false,
// "Dependent" is needed to make "std::enable_if_t<Dependent || Extent <= 0>" SFINAE, // "Dependent" is needed to make "std::enable_if_t<Dependent || Extent <= 0>" SFINAE,
// since "std::enable_if_t<Extent <= 0>" is ill-formed when Extent is greater than 0. // since "std::enable_if_t<Extent <= 0>" is ill-formed when Extent is greater than 0.
class = std::enable_if_t<(Dependent || Extent <= 0)>> class = std::enable_if_t<(Dependent || Extent <= 0)>>
constexpr span() GSL_NOEXCEPT : storage_(nullptr, details::extent_type<0>()) {} constexpr span() GSL_NOEXCEPT : storage_(nullptr, details::extent_type<0>())
{
}
constexpr span(std::nullptr_t) GSL_NOEXCEPT : span() {} constexpr span(std::nullptr_t) GSL_NOEXCEPT : span() {}
@ -368,7 +376,8 @@ public:
} }
template <std::size_t N> template <std::size_t N>
constexpr span(element_type (&arr)[N]) GSL_NOEXCEPT : storage_(&arr[0], details::extent_type<N>()) constexpr span(element_type (&arr)[N]) GSL_NOEXCEPT
: storage_(&arr[0], details::extent_type<N>())
{ {
} }
@ -384,11 +393,18 @@ public:
{ {
} }
template<class ArrayElementType = std::add_pointer<element_type>> template <class ArrayElementType = std::add_pointer<element_type>>
constexpr span(const std::unique_ptr<ArrayElementType>& ptr, index_type count) : storage_(ptr.get(), count) {} constexpr span(const std::unique_ptr<ArrayElementType>& ptr, index_type count)
: storage_(ptr.get(), count)
{
}
constexpr span(const std::unique_ptr<ElementType>& ptr) : storage_(ptr.get(), ptr.get() ? 1 : 0) {} constexpr span(const std::unique_ptr<ElementType>& ptr) : storage_(ptr.get(), ptr.get() ? 1 : 0)
constexpr span(const std::shared_ptr<ElementType>& ptr) : storage_(ptr.get(), ptr.get() ? 1 : 0) {} {
}
constexpr span(const std::shared_ptr<ElementType>& ptr) : storage_(ptr.get(), ptr.get() ? 1 : 0)
{
}
// NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement
// on Container to be a contiguous sequence container. // on Container to be a contiguous sequence container.
@ -498,7 +514,10 @@ public:
constexpr index_type length() const GSL_NOEXCEPT { return size(); } constexpr index_type length() const GSL_NOEXCEPT { return size(); }
constexpr index_type size() const GSL_NOEXCEPT { return storage_.size(); } constexpr index_type size() const GSL_NOEXCEPT { return storage_.size(); }
constexpr index_type length_bytes() const GSL_NOEXCEPT { return size_bytes(); } constexpr index_type length_bytes() const GSL_NOEXCEPT { return size_bytes(); }
constexpr index_type size_bytes() const GSL_NOEXCEPT { return size() * narrow_cast<index_type>(sizeof(element_type)); } constexpr index_type size_bytes() const GSL_NOEXCEPT
{
return size() * narrow_cast<index_type>(sizeof(element_type));
}
constexpr bool empty() const GSL_NOEXCEPT { return size() == 0; } constexpr bool empty() const GSL_NOEXCEPT { return size() == 0; }
// [span.elem], span element access // [span.elem], span element access
@ -551,7 +570,7 @@ private:
// [span.comparison], span comparison operators // [span.comparison], span comparison operators
template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent> template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent>
inline constexpr bool operator==(const span<ElementType, FirstExtent>& l, inline constexpr bool operator==(const span<ElementType, FirstExtent>& l,
const span<ElementType, SecondExtent>& r) const span<ElementType, SecondExtent>& r)
{ {
#ifdef GSL_MSVC_NO_CPP14_STD_EQUAL #ifdef GSL_MSVC_NO_CPP14_STD_EQUAL
return (l.size() == r.size()) && std::equal(l.begin(), l.end(), r.begin()); return (l.size() == r.size()) && std::equal(l.begin(), l.end(), r.begin());
@ -561,31 +580,36 @@ inline constexpr bool operator==(const span<ElementType, FirstExtent>& l,
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
inline constexpr bool operator!=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) inline constexpr bool operator!=(const span<ElementType, Extent>& l,
const span<ElementType, Extent>& r)
{ {
return !(l == r); return !(l == r);
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
inline constexpr bool operator<(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) inline constexpr bool operator<(const span<ElementType, Extent>& l,
const span<ElementType, Extent>& r)
{ {
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
inline constexpr bool operator<=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) inline constexpr bool operator<=(const span<ElementType, Extent>& l,
const span<ElementType, Extent>& r)
{ {
return !(l > r); return !(l > r);
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
inline constexpr bool operator>(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) inline constexpr bool operator>(const span<ElementType, Extent>& l,
const span<ElementType, Extent>& r)
{ {
return r < l; return r < l;
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
inline constexpr bool operator>=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) inline constexpr bool operator>=(const span<ElementType, Extent>& l,
const span<ElementType, Extent>& r)
{ {
return !(l < r); return !(l < r);
} }
@ -633,40 +657,46 @@ as_writeable_bytes(span<ElementType, Extent> s) GSL_NOEXCEPT
// make_span() - Utility functions for creating spans // make_span() - Utility functions for creating spans
// //
template <class ElementType> template <class ElementType>
span<ElementType> span<ElementType> make_span(ElementType* ptr, typename span<ElementType>::index_type count)
make_span(ElementType* ptr, typename span<ElementType>::index_type count) {
{ return span<ElementType>(ptr, count); } return span<ElementType>(ptr, count);
}
template <class ElementType> template <class ElementType>
span<ElementType> span<ElementType> make_span(ElementType* firstElem, ElementType* lastElem)
make_span(ElementType* firstElem, ElementType* lastElem) {
{ return span<ElementType>(firstElem, lastElem); } return span<ElementType>(firstElem, lastElem);
}
template <class ElementType, std::size_t N> template <class ElementType, std::size_t N>
span<ElementType> span<ElementType> make_span(ElementType (&arr)[N])
make_span(ElementType (&arr)[N]) {
{ return span<ElementType>(arr); } return span<ElementType>(arr);
}
template <class Container> template <class Container>
span<typename Container::value_type> span<typename Container::value_type> make_span(Container& cont)
make_span(Container &cont) {
{ return span<typename Container::value_type>(cont); } return span<typename Container::value_type>(cont);
}
template <class Container> template <class Container>
span<const typename Container::value_type> span<const typename Container::value_type> make_span(const Container& cont)
make_span(const Container &cont) {
{ return span<const typename Container::value_type>(cont); } return span<const typename Container::value_type>(cont);
}
template <class Ptr> template <class Ptr>
span<typename Ptr::element_type> span<typename Ptr::element_type> make_span(Ptr& cont, std::ptrdiff_t count)
make_span(Ptr& cont, std::ptrdiff_t count) {
{ return span<typename Ptr::element_type>(cont, count); } return span<typename Ptr::element_type>(cont, count);
}
template <class Ptr> template <class Ptr>
span<typename Ptr::element_type> span<typename Ptr::element_type> make_span(Ptr& cont)
make_span(Ptr& cont) {
{ return span<typename Ptr::element_type>(cont); } return span<typename Ptr::element_type>(cont);
}
// Specialization of gsl::at for span // Specialization of gsl::at for span
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
@ -681,24 +711,24 @@ inline constexpr ElementType& at(const span<ElementType, Extent>& s, std::ptrdif
#undef GSL_NOEXCEPT #undef GSL_NOEXCEPT
#ifdef _MSC_VER #ifdef _MSC_VER
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#undef noexcept #undef noexcept
#pragma pop_macro("noexcept") #pragma pop_macro("noexcept")
#undef alignof #undef alignof
#pragma pop_macro("alignof") #pragma pop_macro("alignof")
#undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG #undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG
#undef GSL_MSVC_NO_DEFAULT_MOVE_CTOR #undef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
#undef GSL_MSVC_NO_CPP14_STD_EQUAL #undef GSL_MSVC_NO_CPP14_STD_EQUAL
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER #endif // _MSC_VER
#endif // GSL_SPAN_H #endif // GSL_SPAN_H

View File

@ -22,41 +22,42 @@
#include <gsl/gsl_assert> #include <gsl/gsl_assert>
#include <gsl/gsl_util> #include <gsl/gsl_util>
#include <gsl/span> #include <gsl/span>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <string> #include <string>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
// blanket turn off warnings from CppCoreCheck for now // blanket turn off warnings from CppCoreCheck for now
// so people aren't annoyed by them when running the tool. // so people aren't annoyed by them when running the tool.
// more targeted suppressions will be added in a future update to the GSL // more targeted suppressions will be added in a future update to the GSL
#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495) #pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr /*constexpr*/ #define constexpr /*constexpr*/
// VS 2013 workarounds // VS 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#define GSL_MSVC_HAS_TYPE_DEDUCTION_BUG #define GSL_MSVC_HAS_TYPE_DEDUCTION_BUG
#define GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE #define GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE
#define GSL_MSVC_NO_CPP14_STD_EQUAL #define GSL_MSVC_NO_CPP14_STD_EQUAL
#define GSL_MSVC_NO_DEFAULT_MOVE_CTOR #define GSL_MSVC_NO_DEFAULT_MOVE_CTOR
// noexcept is not understood // noexcept is not understood
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept /*noexcept*/ #define noexcept /*noexcept*/
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#endif // _MSC_VER #endif // _MSC_VER
// In order to test the library, we need it to throw exceptions that we can catch // In order to test the library, we need it to throw exceptions that we can catch
#ifdef GSL_THROW_ON_CONTRACT_VIOLATION #ifdef GSL_THROW_ON_CONTRACT_VIOLATION
#define GSL_NOEXCEPT /*noexcept*/ #define GSL_NOEXCEPT /*noexcept*/
#else #else
#define GSL_NOEXCEPT noexcept #define GSL_NOEXCEPT noexcept
#endif // GSL_THROW_ON_CONTRACT_VIOLATION #endif // GSL_THROW_ON_CONTRACT_VIOLATION
namespace gsl namespace gsl
@ -89,30 +90,26 @@ using wzstring = basic_zstring<wchar_t, Extent>;
namespace details namespace details
{ {
inline std::ptrdiff_t string_length(const char *str, std::ptrdiff_t n) inline std::ptrdiff_t string_length(const char* str, std::ptrdiff_t n)
{ {
if (str == nullptr || n <= 0) if (str == nullptr || n <= 0) return 0;
return 0;
span<const char> str_span{str, n}; span<const char> str_span{str, n};
std::ptrdiff_t len = 0; std::ptrdiff_t len = 0;
while (len < n && str_span[len]) while (len < n && str_span[len]) len++;
len++;
return len; return len;
} }
inline std::ptrdiff_t wstring_length(const wchar_t *str, std::ptrdiff_t n) inline std::ptrdiff_t wstring_length(const wchar_t* str, std::ptrdiff_t n)
{ {
if (str == nullptr || n <= 0) if (str == nullptr || n <= 0) return 0;
return 0;
span<const wchar_t> str_span{str, n}; span<const wchar_t> str_span{str, n};
std::ptrdiff_t len = 0; std::ptrdiff_t len = 0;
while (len < n && str_span[len]) while (len < n && str_span[len]) len++;
len++;
return len; return len;
} }
@ -316,7 +313,8 @@ public:
} }
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>> template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) GSL_NOEXCEPT : span_(arr) constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) GSL_NOEXCEPT
: span_(arr)
{ {
} }
@ -484,14 +482,11 @@ inline std::wstring to_string(wstring_span<> view)
#endif #endif
template <typename CharT, template <typename CharT, typename Traits = typename std::char_traits<CharT>,
typename Traits = typename std::char_traits<CharT>, typename Allocator = std::allocator<CharT>, typename gCharT, std::ptrdiff_t Extent>
typename Allocator = std::allocator<CharT>,
typename gCharT,
std::ptrdiff_t Extent>
std::basic_string<CharT, Traits, Allocator> to_basic_string(basic_string_span<gCharT, Extent> view) std::basic_string<CharT, Traits, Allocator> to_basic_string(basic_string_span<gCharT, Extent> view)
{ {
return {view.data(), static_cast<std::size_t>(view.length())}; return {view.data(), static_cast<std::size_t>(view.length())};
} }
// zero-terminated string span, used to convert // zero-terminated string span, used to convert
@ -830,23 +825,23 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_N
#undef GSL_NOEXCEPT #undef GSL_NOEXCEPT
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
// VS 2013 workarounds // VS 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
#undef noexcept #undef noexcept
#pragma pop_macro("noexcept") #pragma pop_macro("noexcept")
#undef GSL_MSVC_HAS_TYPE_DEDUCTION_BUG #undef GSL_MSVC_HAS_TYPE_DEDUCTION_BUG
#undef GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE #undef GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE
#undef GSL_MSVC_NO_CPP14_STD_EQUAL #undef GSL_MSVC_NO_CPP14_STD_EQUAL
#undef GSL_MSVC_NO_DEFAULT_MOVE_CTOR #undef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#endif // _MSC_VER #endif // _MSC_VER
#endif // GSL_STRING_SPAN_H #endif // GSL_STRING_SPAN_H

View File

@ -15,6 +15,7 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/gsl_algorithm> #include <gsl/gsl_algorithm>
#include <array> #include <array>
@ -179,8 +180,8 @@ SUITE(copy_tests)
span<int*, 4> dst_span_static(dst); span<int*, 4> dst_span_static(dst);
// every line should produce a compilation error // every line should produce a compilation error
copy(src_span_dyn, dst_span_dyn); copy(src_span_dyn, dst_span_dyn);
copy(src_span_dyn, dst_span_static); copy(src_span_dyn, dst_span_static);
copy(src_span_static, dst_span_dyn); copy(src_span_static, dst_span_dyn);
copy(src_span_static, dst_span_static); copy(src_span_static, dst_span_static);
} }
@ -196,9 +197,9 @@ SUITE(copy_tests)
span<int> dst_span_dyn(dst); span<int> dst_span_dyn(dst);
span<int, 4> dst_span_static(dst); span<int, 4> dst_span_static(dst);
CHECK_THROW(copy(src_span_dyn, dst_span_dyn), fail_fast); CHECK_THROW(copy(src_span_dyn, dst_span_dyn), fail_fast);
CHECK_THROW(copy(src_span_dyn, dst_span_static), fail_fast); CHECK_THROW(copy(src_span_dyn, dst_span_static), fail_fast);
CHECK_THROW(copy(src_span_static, dst_span_dyn), fail_fast); CHECK_THROW(copy(src_span_static, dst_span_dyn), fail_fast);
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static); copy(src_span_static, dst_span_static);

View File

@ -1,20 +1,21 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2015 Microsoft Corporation. All rights reserved. // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// //
// This code is licensed under the MIT License (MIT). // This code is licensed under the MIT License (MIT).
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/gsl> #include <gsl/gsl>
using namespace gsl; using namespace gsl;
@ -34,7 +35,7 @@ SUITE(assertion_tests)
} }
int g(int i) int g(int i)
{ {
i++; i++;
Ensures(i > 0 && i < 10); Ensures(i > 0 && i < 10);
return i; return i;
@ -47,7 +48,4 @@ SUITE(assertion_tests)
} }
} }
int main(int, const char *[]) int main(int, const char* []) { return UnitTest::RunAllTests(); }
{
return UnitTest::RunAllTests();
}

View File

@ -15,9 +15,11 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/gsl> #include <gsl/gsl>
#include <vector>
#include <initializer_list> #include <initializer_list>
#include <vector>
using gsl::fail_fast; using gsl::fail_fast;
@ -25,8 +27,8 @@ SUITE(at_tests)
{ {
TEST(static_array) TEST(static_array)
{ {
int a[4] = { 1, 2, 3, 4 }; int a[4] = {1, 2, 3, 4};
const int (&c_a)[4] = a; const int(&c_a)[4] = a;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
CHECK(&gsl::at(a, i) == &a[i]); CHECK(&gsl::at(a, i) == &a[i]);
@ -41,7 +43,7 @@ SUITE(at_tests)
TEST(std_array) TEST(std_array)
{ {
std::array<int, 4> a = { 1, 2, 3, 4 }; std::array<int, 4> a = {1, 2, 3, 4};
const std::array<int, 4>& c_a = a; const std::array<int, 4>& c_a = a;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -57,7 +59,7 @@ SUITE(at_tests)
TEST(StdVector) TEST(StdVector)
{ {
std::vector<int> a = { 1, 2, 3, 4 }; std::vector<int> a = {1, 2, 3, 4};
const std::vector<int>& c_a = a; const std::vector<int>& c_a = a;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -73,26 +75,26 @@ SUITE(at_tests)
TEST(InitializerList) TEST(InitializerList)
{ {
std::initializer_list<int> a = { 1, 2, 3, 4 }; std::initializer_list<int> a = {1, 2, 3, 4};
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
CHECK(gsl::at(a, i) == i+1); CHECK(gsl::at(a, i) == i + 1);
CHECK(gsl::at({1,2,3,4}, i) == i+1); CHECK(gsl::at({1, 2, 3, 4}, i) == i + 1);
} }
CHECK_THROW(gsl::at(a, -1), fail_fast); CHECK_THROW(gsl::at(a, -1), fail_fast);
CHECK_THROW(gsl::at(a, 4), fail_fast); CHECK_THROW(gsl::at(a, 4), fail_fast);
CHECK_THROW(gsl::at({1,2,3,4}, -1), fail_fast); CHECK_THROW(gsl::at({1, 2, 3, 4}, -1), fail_fast);
CHECK_THROW(gsl::at({1,2,3,4}, 4), fail_fast); CHECK_THROW(gsl::at({1, 2, 3, 4}, 4), fail_fast);
} }
} }
#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910 #if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910
static constexpr bool test_constexpr() static constexpr bool test_constexpr()
{ {
int a1[4] = { 1, 2, 3, 4 }; int a1[4] = {1, 2, 3, 4};
const int (&c_a1)[4] = a1; const int(&c_a1)[4] = a1;
std::array<int,4> a2 = { 1, 2, 3, 4 }; std::array<int, 4> a2 = {1, 2, 3, 4};
const std::array<int, 4>& c_a2 = a2; const std::array<int, 4>& c_a2 = a2;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -101,7 +103,7 @@ static constexpr bool test_constexpr()
// requires C++17: // requires C++17:
// if (&gsl::at(a2, i) != &a2[static_cast<std::size_t>(i)]) return false; // if (&gsl::at(a2, i) != &a2[static_cast<std::size_t>(i)]) return false;
if (&gsl::at(c_a2, i) != &c_a2[static_cast<std::size_t>(i)]) return false; if (&gsl::at(c_a2, i) != &c_a2[static_cast<std::size_t>(i)]) return false;
if (gsl::at({1,2,3,4}, i) != i+1) return false; if (gsl::at({1, 2, 3, 4}, i) != i + 1) return false;
} }
return true; return true;
@ -110,7 +112,4 @@ static constexpr bool test_constexpr()
static_assert(test_constexpr(), "FAIL"); static_assert(test_constexpr(), "FAIL");
#endif #endif
int main() int main() { return UnitTest::RunAllTests(); }
{
return UnitTest::RunAllTests();
}

View File

@ -15,7 +15,9 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/multi_span> #include <gsl/multi_span>
#include <vector> #include <vector>
using namespace std; using namespace std;
@ -23,81 +25,76 @@ using namespace gsl;
namespace namespace
{ {
void use(std::ptrdiff_t&) {} void use(std::ptrdiff_t&) {}
} }
SUITE(bounds_test) SUITE(bounds_test)
{ {
TEST(basic_bounds) TEST(basic_bounds)
{ {
for (auto point : static_bounds<dynamic_range, 3, 4 > { 2 }) for (auto point : static_bounds<dynamic_range, 3, 4>{2}) {
{ for (decltype(point)::size_type j = 0;
for (decltype(point)::size_type j = 0; j < static_cast<decltype(point)::size_type>(decltype(point)::rank); j++)
j < static_cast<decltype(point)::size_type>(decltype(point)::rank); {
j++) use(j);
{ use(point[static_cast<std::size_t>(j)]);
use(j); }
use(point[static_cast<std::size_t>(j)]); }
} }
}
}
TEST(bounds_basic) TEST(bounds_basic)
{ {
static_bounds<3, 4, 5> b; static_bounds<3, 4, 5> b;
const auto a = b.slice(); const auto a = b.slice();
(void)a; (void) a;
static_bounds<4, dynamic_range, 2> x{ 4 }; static_bounds<4, dynamic_range, 2> x{4};
x.slice().slice(); x.slice().slice();
} }
TEST (arrayview_iterator) TEST(arrayview_iterator)
{ {
static_bounds<4, dynamic_range, 2> bounds{ 3 }; static_bounds<4, dynamic_range, 2> bounds{3};
const auto itr = bounds.begin(); const auto itr = bounds.begin();
(void)itr; (void) itr;
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
multi_span<int, 4, dynamic_range, 2> av(nullptr, bounds); multi_span<int, 4, dynamic_range, 2> av(nullptr, bounds);
auto itr2 = av.cbegin(); auto itr2 = av.cbegin();
for (auto& v : av) { for (auto& v : av) {
v = 4; v = 4;
} }
fill(av.begin(), av.end(), 0); fill(av.begin(), av.end(), 0);
#endif #endif
} }
TEST (bounds_convertible) TEST(bounds_convertible)
{ {
static_bounds<7, 4, 2> b1; static_bounds<7, 4, 2> b1;
static_bounds<7, dynamic_range, 2> b2 = b1; static_bounds<7, dynamic_range, 2> b2 = b1;
(void)b2; (void) b2;
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
static_bounds<7, dynamic_range, 1> b4 = b2; static_bounds<7, dynamic_range, 1> b4 = b2;
#endif #endif
static_bounds<dynamic_range, dynamic_range, dynamic_range> b3 = b1; static_bounds<dynamic_range, dynamic_range, dynamic_range> b3 = b1;
static_bounds<7, 4, 2> b4 = b3; static_bounds<7, 4, 2> b4 = b3;
(void)b4; (void) b4;
static_bounds<dynamic_range> b11; static_bounds<dynamic_range> b11;
static_bounds<dynamic_range> b5; static_bounds<dynamic_range> b5;
static_bounds<34> b6; static_bounds<34> b6;
b5 = static_bounds<20>(); b5 = static_bounds<20>();
CHECK_THROW(b6 = b5, fail_fast); CHECK_THROW(b6 = b5, fail_fast);
b5 = static_bounds<34>(); b5 = static_bounds<34>();
b6 = b5; b6 = b5;
CHECK(b5 == b6); CHECK(b5 == b6);
CHECK(b5.size() == b6.size()); CHECK(b5.size() == b6.size());
} }
} }
int main(int, const char *[]) int main(int, const char* []) { return UnitTest::RunAllTests(); }
{
return UnitTest::RunAllTests();
}

View File

@ -15,6 +15,7 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/gsl_byte> #include <gsl/gsl_byte>
#include <iostream> #include <iostream>
@ -111,11 +112,11 @@ SUITE(byte_tests)
CHECK(0x12 == gsl::to_integer<unsigned long>(b)); CHECK(0x12 == gsl::to_integer<unsigned long>(b));
CHECK(0x12 == gsl::to_integer<unsigned long long>(b)); CHECK(0x12 == gsl::to_integer<unsigned long long>(b));
// CHECK(0x12 == gsl::to_integer<float>(b)); // expect compile-time error // CHECK(0x12 == gsl::to_integer<float>(b)); // expect compile-time error
// CHECK(0x12 == gsl::to_integer<double>(b)); // expect compile-time error // CHECK(0x12 == gsl::to_integer<double>(b)); // expect compile-time error
} }
int modify_both(gsl::byte& b, int& i) int modify_both(gsl::byte & b, int& i)
{ {
i = 10; i = 10;
b = to_byte<5>(); b = to_byte<5>();
@ -124,12 +125,11 @@ SUITE(byte_tests)
TEST(aliasing) TEST(aliasing)
{ {
int i{ 0 }; int i{0};
const int res = modify_both(reinterpret_cast<byte&>(i), i); const int res = modify_both(reinterpret_cast<byte&>(i), i);
CHECK(res == i); CHECK(res == i);
} }
} }
} }
int main(int, const char* []) { return UnitTest::RunAllTests(); } int main(int, const char* []) { return UnitTest::RunAllTests(); }

View File

@ -15,6 +15,7 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/multi_span> #include <gsl/multi_span>
#include <iostream> #include <iostream>
@ -668,7 +669,9 @@ SUITE(multi_span_tests)
CHECK(s2.empty()); CHECK(s2.empty());
auto get_temp_span = [&]() -> multi_span<int> { return {&arr[1], 2}; }; auto get_temp_span = [&]() -> multi_span<int> { return {&arr[1], 2}; };
auto use_span = [&](multi_span<const int> s) { CHECK(s.length() == 2 && s.data() == &arr[1]); }; auto use_span = [&](multi_span<const int> s) {
CHECK(s.length() == 2 && s.data() == &arr[1]);
};
use_span(get_temp_span()); use_span(get_temp_span());
s1 = get_temp_span(); s1 = get_temp_span();
@ -1028,7 +1031,7 @@ SUITE(multi_span_tests)
int arr[] = {1, 2, 3}; int arr[] = {1, 2, 3};
multi_span<int> s1 = {&arr[0], 2}; // shorter multi_span<int> s1 = {&arr[0], 2}; // shorter
multi_span<int> s2 = arr; // longer multi_span<int> s2 = arr; // longer
CHECK(s1 != s2); CHECK(s1 != s2);
CHECK(s2 != s1); CHECK(s2 != s1);
@ -1283,412 +1286,411 @@ SUITE(multi_span_tests)
delete[] arr; delete[] arr;
} }
TEST(index_constructors) TEST(index_constructors){{// components of the same type
{ index<3> i1(0, 1, 2);
{ CHECK(i1[0] == 0);
// components of the same type
index<3> i1(0, 1, 2);
CHECK(i1[0] == 0);
// components of different types // components of different types
std::size_t c0 = 0; std::size_t c0 = 0;
std::size_t c1 = 1; std::size_t c1 = 1;
index<3> i2(c0, c1, 2); index<3> i2(c0, c1, 2);
CHECK(i2[0] == 0); CHECK(i2[0] == 0);
// from array // from array
index<3> i3 = {0, 1, 2}; index<3> i3 = {0, 1, 2};
CHECK(i3[0] == 0); CHECK(i3[0] == 0);
// from other index of the same size type // from other index of the same size type
index<3> i4 = i3; index<3> i4 = i3;
CHECK(i4[0] == 0); CHECK(i4[0] == 0);
// default // default
index<3> i7; index<3> i7;
CHECK(i7[0] == 0); CHECK(i7[0] == 0);
// default // default
index<3> i9 = {}; index<3> i9 = {};
CHECK(i9[0] == 0); CHECK(i9[0] == 0);
} }
{ {
// components of the same type // components of the same type
index<1> i1(0); index<1> i1(0);
CHECK(i1[0] == 0); CHECK(i1[0] == 0);
// components of different types // components of different types
std::size_t c0 = 0; std::size_t c0 = 0;
index<1> i2(c0); index<1> i2(c0);
CHECK(i2[0] == 0); CHECK(i2[0] == 0);
// from array // from array
index<1> i3 = {0}; index<1> i3 = {0};
CHECK(i3[0] == 0); CHECK(i3[0] == 0);
// from int // from int
index<1> i4 = 0; index<1> i4 = 0;
CHECK(i4[0] == 0); CHECK(i4[0] == 0);
// from other index of the same size type // from other index of the same size type
index<1> i5 = i3; index<1> i5 = i3;
CHECK(i5[0] == 0); CHECK(i5[0] == 0);
// default // default
index<1> i8; index<1> i8;
CHECK(i8[0] == 0); CHECK(i8[0] == 0);
// default // default
index<1> i9 = {}; index<1> i9 = {};
CHECK(i9[0] == 0); CHECK(i9[0] == 0);
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
index<3> i1(0, 1); index<3> i1(0, 1);
index<3> i2(0, 1, 2, 3); index<3> i2(0, 1, 2, 3);
index<3> i3 = {0}; index<3> i3 = {0};
index<3> i4 = {0, 1, 2, 3}; index<3> i4 = {0, 1, 2, 3};
index<1> i5 = {0, 1}; index<1> i5 = {0, 1};
} }
#endif #endif
} }
TEST(index_operations)
{
ptrdiff_t a[3] = {0, 1, 2};
ptrdiff_t b[3] = {3, 4, 5};
index<3> i = a;
index<3> j = b;
CHECK(i[0] == 0);
CHECK(i[1] == 1);
CHECK(i[2] == 2);
TEST(index_operations)
{ {
ptrdiff_t a[3] = {0, 1, 2}; index<3> k = i + j;
ptrdiff_t b[3] = {3, 4, 5};
index<3> i = a;
index<3> j = b;
CHECK(i[0] == 0); CHECK(i[0] == 0);
CHECK(i[1] == 1); CHECK(i[1] == 1);
CHECK(i[2] == 2); CHECK(i[2] == 2);
CHECK(k[0] == 3);
{ CHECK(k[1] == 5);
index<3> k = i + j; CHECK(k[2] == 7);
CHECK(i[0] == 0);
CHECK(i[1] == 1);
CHECK(i[2] == 2);
CHECK(k[0] == 3);
CHECK(k[1] == 5);
CHECK(k[2] == 7);
}
{
index<3> k = i * 3;
CHECK(i[0] == 0);
CHECK(i[1] == 1);
CHECK(i[2] == 2);
CHECK(k[0] == 0);
CHECK(k[1] == 3);
CHECK(k[2] == 6);
}
{
index<3> k = 3 * i;
CHECK(i[0] == 0);
CHECK(i[1] == 1);
CHECK(i[2] == 2);
CHECK(k[0] == 0);
CHECK(k[1] == 3);
CHECK(k[2] == 6);
}
{
index<2> k = details::shift_left(i);
CHECK(i[0] == 0);
CHECK(i[1] == 1);
CHECK(i[2] == 2);
CHECK(k[0] == 1);
CHECK(k[1] == 2);
}
} }
void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
{ {
auto length = av.size() / 2; index<3> k = i * 3;
// view to the second column CHECK(i[0] == 0);
auto section = av.section({0, 1}, {length, 1}); CHECK(i[1] == 1);
CHECK(i[2] == 2);
CHECK(k[0] == 0);
CHECK(k[1] == 3);
CHECK(k[2] == 6);
}
CHECK(section.size() == length); {
for (auto i = 0; i < section.size(); ++i) { index<3> k = 3 * i;
CHECK(section[i][0] == av[i][1]);
}
for (auto i = 0; i < section.size(); ++i) { CHECK(i[0] == 0);
auto idx = index<2>{i, 0}; // avoid braces inside the CHECK macro CHECK(i[1] == 1);
CHECK(i[2] == 2);
CHECK(k[0] == 0);
CHECK(k[1] == 3);
CHECK(k[2] == 6);
}
{
index<2> k = details::shift_left(i);
CHECK(i[0] == 0);
CHECK(i[1] == 1);
CHECK(i[2] == 2);
CHECK(k[0] == 1);
CHECK(k[1] == 2);
}
}
void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
{
auto length = av.size() / 2;
// view to the second column
auto section = av.section({0, 1}, {length, 1});
CHECK(section.size() == length);
for (auto i = 0; i < section.size(); ++i) {
CHECK(section[i][0] == av[i][1]);
}
for (auto i = 0; i < section.size(); ++i) {
auto idx = index<2>{i, 0}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]);
}
CHECK(section.bounds().index_bounds()[0] == length);
CHECK(section.bounds().index_bounds()[1] == 1);
for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) {
for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) {
auto idx = index<2>{i, j}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]); CHECK(section[idx] == av[i][1]);
} }
CHECK(section.bounds().index_bounds()[0] == length);
CHECK(section.bounds().index_bounds()[1] == 1);
for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) {
for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) {
auto idx = index<2>{i, j}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]);
}
}
auto check_sum = 0;
for (auto i = 0; i < length; ++i) {
check_sum += av[i][1];
}
{
auto idx = 0;
auto sum = 0;
for (auto num : section) {
CHECK(num == av[idx][1]);
sum += num;
idx++;
}
CHECK(sum == check_sum);
}
{
auto idx = length - 1;
auto sum = 0;
for (auto iter = section.rbegin(); iter != section.rend(); ++iter) {
CHECK(*iter == av[idx][1]);
sum += *iter;
idx--;
}
CHECK(sum == check_sum);
}
} }
TEST(span_section_iteration) auto check_sum = 0;
{ for (auto i = 0; i < length; ++i) {
int arr[4][2] = {{4, 0}, {5, 1}, {6, 2}, {7, 3}}; check_sum += av[i][1];
// static bounds
{
multi_span<int, 4, 2> av = arr;
iterate_second_column(av);
}
// first bound is dynamic
{
multi_span<int, dynamic_range, 2> av = arr;
iterate_second_column(av);
}
// second bound is dynamic
{
multi_span<int, 4, dynamic_range> av = arr;
iterate_second_column(av);
}
// both bounds are dynamic
{
multi_span<int, dynamic_range, dynamic_range> av = arr;
iterate_second_column(av);
}
} }
TEST(dynamic_span_section_iteration)
{ {
auto height = 4, width = 2; auto idx = 0;
auto size = height * width; auto sum = 0;
for (auto num : section) {
auto arr = new int[static_cast<std::size_t>(size)]; CHECK(num == av[idx][1]);
for (auto i = 0; i < size; ++i) { sum += num;
arr[i] = i; idx++;
} }
auto av = as_multi_span(arr, size); CHECK(sum == check_sum);
}
// first bound is dynamic {
{ auto idx = length - 1;
multi_span<int, dynamic_range, 2> av2 = as_multi_span(av, dim(height), dim(width)); auto sum = 0;
iterate_second_column(av2); for (auto iter = section.rbegin(); iter != section.rend(); ++iter) {
} CHECK(*iter == av[idx][1]);
// second bound is dynamic sum += *iter;
{ idx--;
multi_span<int, 4, dynamic_range> av2 = as_multi_span(av, dim(height), dim(width));
iterate_second_column(av2);
}
// both bounds are dynamic
{
multi_span<int, dynamic_range, dynamic_range> av2 = as_multi_span(av, dim(height), dim(width));
iterate_second_column(av2);
} }
delete[] arr; CHECK(sum == check_sum);
}
}
TEST(span_section_iteration)
{
int arr[4][2] = {{4, 0}, {5, 1}, {6, 2}, {7, 3}};
// static bounds
{
multi_span<int, 4, 2> av = arr;
iterate_second_column(av);
}
// first bound is dynamic
{
multi_span<int, dynamic_range, 2> av = arr;
iterate_second_column(av);
}
// second bound is dynamic
{
multi_span<int, 4, dynamic_range> av = arr;
iterate_second_column(av);
}
// both bounds are dynamic
{
multi_span<int, dynamic_range, dynamic_range> av = arr;
iterate_second_column(av);
}
}
TEST(dynamic_span_section_iteration)
{
auto height = 4, width = 2;
auto size = height * width;
auto arr = new int[static_cast<std::size_t>(size)];
for (auto i = 0; i < size; ++i) {
arr[i] = i;
} }
TEST(span_structure_size) auto av = as_multi_span(arr, size);
// first bound is dynamic
{ {
double(*arr)[3][4] = new double[100][3][4]; multi_span<int, dynamic_range, 2> av2 = as_multi_span(av, dim(height), dim(width));
multi_span<double, dynamic_range, 3, 4> av1(arr, 10); iterate_second_column(av2);
}
struct EffectiveStructure // second bound is dynamic
{ {
double* v1; multi_span<int, 4, dynamic_range> av2 = as_multi_span(av, dim(height), dim(width));
ptrdiff_t v2; iterate_second_column(av2);
}; }
CHECK(sizeof(av1) == sizeof(EffectiveStructure)); // both bounds are dynamic
{
CHECK_THROW(av1[10][3][4], fail_fast); multi_span<int, dynamic_range, dynamic_range> av2 =
as_multi_span(av, dim(height), dim(width));
multi_span<const double, dynamic_range, 6, 4> av2 = as_multi_span(av1, dim(5), dim<6>(), dim<4>()); iterate_second_column(av2);
(void) av2;
} }
TEST(fixed_size_conversions) delete[] arr;
}
TEST(span_structure_size)
{
double(*arr)[3][4] = new double[100][3][4];
multi_span<double, dynamic_range, 3, 4> av1(arr, 10);
struct EffectiveStructure
{ {
int arr[] = {1, 2, 3, 4}; double* v1;
ptrdiff_t v2;
};
CHECK(sizeof(av1) == sizeof(EffectiveStructure));
// converting to an multi_span from an equal size array is ok CHECK_THROW(av1[10][3][4], fail_fast);
multi_span<int, 4> av4 = arr;
CHECK(av4.length() == 4);
// converting to dynamic_range a_v is always ok multi_span<const double, dynamic_range, 6, 4> av2 =
{ as_multi_span(av1, dim(5), dim<6>(), dim<4>());
multi_span<int, dynamic_range> av = av4; (void) av2;
(void) av; }
}
{ TEST(fixed_size_conversions)
multi_span<int, dynamic_range> av = arr; {
(void) av; int arr[] = {1, 2, 3, 4};
}
// converting to an multi_span from an equal size array is ok
multi_span<int, 4> av4 = arr;
CHECK(av4.length() == 4);
// converting to dynamic_range a_v is always ok
{
multi_span<int, dynamic_range> av = av4;
(void) av;
}
{
multi_span<int, dynamic_range> av = arr;
(void) av;
}
// initialization or assignment to static multi_span that REDUCES size is NOT ok // initialization or assignment to static multi_span that REDUCES size is NOT ok
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
multi_span<int, 2> av2 = arr; multi_span<int, 2> av2 = arr;
} }
{ {
multi_span<int, 2> av2 = av4; multi_span<int, 2> av2 = av4;
} }
#endif #endif
{ {
multi_span<int, dynamic_range> av = arr; multi_span<int, dynamic_range> av = arr;
multi_span<int, 2> av2 = av; multi_span<int, 2> av2 = av;
(void) av2; (void) av2;
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
multi_span<int, dynamic_range> av = arr; multi_span<int, dynamic_range> av = arr;
multi_span<int, 2, 1> av2 = av.as_multi_span(dim<2>(), dim<2>()); multi_span<int, 2, 1> av2 = av.as_multi_span(dim<2>(), dim<2>());
} }
#endif #endif
{ {
multi_span<int, dynamic_range> av = arr; multi_span<int, dynamic_range> av = arr;
multi_span<int, 2, 1> av2 = as_multi_span(av, dim(2), dim(2)); multi_span<int, 2, 1> av2 = as_multi_span(av, dim(2), dim(2));
auto workaround_macro = [&]() { return av2[{1, 0}] == 2; }; auto workaround_macro = [&]() { return av2[{1, 0}] == 2; };
CHECK(workaround_macro()); CHECK(workaround_macro());
} }
// but doing so explicitly is ok // but doing so explicitly is ok
// you can convert statically // you can convert statically
{ {
multi_span<int, 2> av2 = {arr, 2}; multi_span<int, 2> av2 = {arr, 2};
(void) av2; (void) av2;
} }
{ {
multi_span<int, 1> av2 = av4.first<1>(); multi_span<int, 1> av2 = av4.first<1>();
(void) av2; (void) av2;
} }
// ...or dynamically // ...or dynamically
{ {
// NB: implicit conversion to multi_span<int,2> from multi_span<int,dynamic_range> // NB: implicit conversion to multi_span<int,2> from multi_span<int,dynamic_range>
multi_span<int, 1> av2 = av4.first(1); multi_span<int, 1> av2 = av4.first(1);
(void) av2; (void) av2;
} }
// initialization or assignment to static multi_span that requires size INCREASE is not ok. // initialization or assignment to static multi_span that requires size INCREASE is not ok.
int arr2[2] = {1, 2}; int arr2[2] = {1, 2};
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
multi_span<int, 4> av4 = arr2; multi_span<int, 4> av4 = arr2;
} }
{ {
multi_span<int, 2> av2 = arr2; multi_span<int, 2> av2 = arr2;
multi_span<int, 4> av4 = av2; multi_span<int, 4> av4 = av2;
} }
#endif #endif
{ {
auto f = [&]() {
multi_span<int, 4> av9 = {arr2, 2};
(void) av9;
};
CHECK_THROW(f(), fail_fast);
}
// this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one
multi_span<int, dynamic_range> av = arr2;
auto f = [&]() { auto f = [&]() {
multi_span<int, 4> av2 = av; multi_span<int, 4> av9 = {arr2, 2};
(void) av2; (void) av9;
}; };
CHECK_THROW(f(), fail_fast); CHECK_THROW(f(), fail_fast);
} }
TEST(as_writeable_bytes) // this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one
multi_span<int, dynamic_range> av = arr2;
auto f = [&]() {
multi_span<int, 4> av2 = av;
(void) av2;
};
CHECK_THROW(f(), fail_fast);
}
TEST(as_writeable_bytes)
{
int a[] = {1, 2, 3, 4};
{ {
int a[] = {1, 2, 3, 4};
{
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
// you should not be able to get writeable bytes for const objects // you should not be able to get writeable bytes for const objects
multi_span<const int, dynamic_range> av = a; multi_span<const int, dynamic_range> av = a;
auto wav = av.as_writeable_bytes(); auto wav = av.as_writeable_bytes();
#endif #endif
}
{
multi_span<int, dynamic_range> av;
auto wav = as_writeable_bytes(av);
CHECK(wav.length() == av.length());
CHECK(wav.length() == 0);
CHECK(wav.size_bytes() == 0);
}
{
multi_span<int, dynamic_range> av = a;
auto wav = as_writeable_bytes(av);
CHECK(wav.data() == reinterpret_cast<byte*>(&a[0]));
CHECK(static_cast<std::size_t>(wav.length()) == sizeof(a));
}
} }
TEST(iterator)
{ {
int a[] = {1, 2, 3, 4}; multi_span<int, dynamic_range> av;
auto wav = as_writeable_bytes(av);
CHECK(wav.length() == av.length());
CHECK(wav.length() == 0);
CHECK(wav.size_bytes() == 0);
}
{ {
multi_span<int, dynamic_range> av = a; multi_span<int, dynamic_range> av = a;
auto wav = as_writeable_bytes(av); auto wav = as_writeable_bytes(av);
for (auto& b : wav) { CHECK(wav.data() == reinterpret_cast<byte*>(&a[0]));
b = byte(0); CHECK(static_cast<std::size_t>(wav.length()) == sizeof(a));
}
for (std::size_t i = 0; i < 4; ++i) {
CHECK(a[i] == 0);
}
}
{
multi_span<int, dynamic_range> av = a;
for (auto& n : av) {
n = 1;
}
for (std::size_t i = 0; i < 4; ++i) {
CHECK(a[i] == 1);
}
}
} }
} }
TEST(iterator)
{
int a[] = {1, 2, 3, 4};
{
multi_span<int, dynamic_range> av = a;
auto wav = as_writeable_bytes(av);
for (auto& b : wav) {
b = byte(0);
}
for (std::size_t i = 0; i < 4; ++i) {
CHECK(a[i] == 0);
}
}
{
multi_span<int, dynamic_range> av = a;
for (auto& n : av) {
n = 1;
}
for (std::size_t i = 0; i < 4; ++i) {
CHECK(a[i] == 1);
}
}
}
}
int main(int, const char* []) { return UnitTest::RunAllTests(); } int main(int, const char* []) { return UnitTest::RunAllTests(); }

View File

@ -1,33 +1,41 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2015 Microsoft Corporation. All rights reserved. // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// //
// This code is licensed under the MIT License (MIT). // This code is licensed under the MIT License (MIT).
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/gsl> #include <gsl/gsl>
#include <vector>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
using namespace gsl; using namespace gsl;
struct MyBase {}; struct MyBase
struct MyDerived : public MyBase {}; {
struct Unrelated {}; };
struct MyDerived : public MyBase
{
};
struct Unrelated
{
};
// stand-in for a user-defined ref-counted class // stand-in for a user-defined ref-counted class
template<typename T> template <typename T>
struct RefCounted struct RefCounted
{ {
RefCounted(T* p) : p_(p) {} RefCounted(T* p) : p_(p) {}
@ -39,95 +47,97 @@ struct RefCounted
template <typename T> template <typename T>
struct CustomPtr struct CustomPtr
{ {
CustomPtr(T* p) : p_(p) {} CustomPtr(T* p) : p_(p) {}
operator T*() { return p_; } operator T*() { return p_; }
bool operator !=(std::nullptr_t)const { return p_ != nullptr; } bool operator!=(std::nullptr_t) const { return p_ != nullptr; }
T* p_ = nullptr; T* p_ = nullptr;
}; };
template <typename T, typename U> template <typename T, typename U>
std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true" : "false"; return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
} }
template <typename T, typename U> template <typename T, typename U>
std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true" : "false"; return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
} }
template <typename T, typename U> template <typename T, typename U>
std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true" : "false"; return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
} }
template <typename T, typename U> template <typename T, typename U>
std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true" : "false"; return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
} }
template <typename T, typename U> template <typename T, typename U>
std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true" : "false"; return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
} }
template <typename T, typename U> template <typename T, typename U>
std::string operator>=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator>=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true" : "false"; return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
} }
SUITE(NotNullTests) SUITE(NotNullTests)
{ {
bool helper(not_null<int*> p) bool helper(not_null<int*> p) { return *p == 12; }
{
return *p == 12;
}
TEST(TestNotNullConstructors) TEST(TestNotNullConstructors)
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
not_null<int*> p = nullptr; // yay...does not compile! not_null<int*> p = nullptr; // yay...does not compile!
not_null<std::vector<char>*> p = 0; // yay...does not compile! not_null<std::vector<char>*> p = 0; // yay...does not compile!
not_null<int*> p; // yay...does not compile! not_null<int*> p; // yay...does not compile!
std::unique_ptr<int> up = std::make_unique<int>(120); std::unique_ptr<int> up = std::make_unique<int>(120);
not_null<int*> p = up; not_null<int*> p = up;
// Forbid non-nullptr assignable types // Forbid non-nullptr assignable types
not_null<std::vector<int>> f(std::vector<int>{1}); not_null<std::vector<int>> f(std::vector<int>{1});
not_null<int> z(10); not_null<int> z(10);
not_null<std::vector<int>> y({1,2}); not_null<std::vector<int>> y({1, 2});
#endif #endif
int i = 12; int i = 12;
auto rp = RefCounted<int>(&i); auto rp = RefCounted<int>(&i);
not_null<int*> p(rp); not_null<int*> p(rp);
CHECK(p.get() == &i); CHECK(p.get() == &i);
not_null<std::shared_ptr<int>> x(std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable not_null<std::shared_ptr<int>> x(
std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
} }
TEST(TestNotNullCasting) TEST(TestNotNullCasting)
{ {
MyBase base; MyBase base;
MyDerived derived; MyDerived derived;
Unrelated unrelated; Unrelated unrelated;
not_null<Unrelated*> u = &unrelated; not_null<Unrelated*> u = &unrelated;
(void)u; (void) u;
not_null<MyDerived*> p = &derived; not_null<MyDerived*> p = &derived;
not_null<MyBase*> q = &base; not_null<MyBase*> q = &base;
q = p; // allowed with heterogeneous copy ctor q = p; // allowed with heterogeneous copy ctor
CHECK(q == p); CHECK(q == p);
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
q = u; // no viable conversion possible between MyBase* and Unrelated* q = u; // no viable conversion possible between MyBase* and Unrelated*
p = q; // not possible to implicitly convert MyBase* to MyDerived* p = q; // not possible to implicitly convert MyBase* to MyDerived*
not_null<Unrelated*> r = p; not_null<Unrelated*> r = p;
not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p); not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
@ -139,7 +149,7 @@ SUITE(NotNullTests)
TEST(TestNotNullAssignment) TEST(TestNotNullAssignment)
{ {
int i = 12; int i = 12;
not_null<int*> p = &i; not_null<int*> p = &i;
CHECK(helper(p)); CHECK(helper(p));
int* q = nullptr; int* q = nullptr;
@ -211,7 +221,7 @@ SUITE(NotNullTests)
TEST(TestNotNullCustomPtrComparison) TEST(TestNotNullCustomPtrComparison)
{ {
int ints[2] = { 42, 43 }; int ints[2] = {42, 43};
CustomPtr<int> p1(&ints[0]); CustomPtr<int> p1(&ints[0]);
CustomPtr<const int> p2(&ints[1]); CustomPtr<const int> p2(&ints[1]);
@ -242,7 +252,4 @@ SUITE(NotNullTests)
} }
} }
int main(int, const char *[]) int main(int, const char* []) { return UnitTest::RunAllTests(); }
{
return UnitTest::RunAllTests();
}

View File

@ -1,31 +1,30 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2015 Microsoft Corporation. All rights reserved. // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// //
// This code is licensed under the MIT License (MIT). // This code is licensed under the MIT License (MIT).
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/gsl> #include <gsl/gsl>
#include <functional> #include <functional>
using namespace gsl; using namespace gsl;
SUITE(owner_tests) SUITE(owner_tests)
{ {
void f(int* i) void f(int* i) { *i += 1; }
{
*i += 1;
}
TEST(basic_test) TEST(basic_test)
{ {
@ -37,7 +36,4 @@ SUITE(owner_tests)
} }
} }
int main(int, const char *[]) int main(int, const char* []) { return UnitTest::RunAllTests(); }
{
return UnitTest::RunAllTests();
}

File diff suppressed because it is too large Load Diff

View File

@ -15,34 +15,39 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/multi_span> #include <gsl/multi_span>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <list>
#include <iostream>
#include <memory>
#include <map>
using namespace std; using namespace std;
using namespace gsl; using namespace gsl;
namespace namespace
{ {
struct BaseClass {}; struct BaseClass
struct DerivedClass : BaseClass {}; {
};
struct DerivedClass : BaseClass
{
};
} }
SUITE(strided_span_tests) SUITE(strided_span_tests)
{ {
TEST (span_section_test) TEST(span_section_test)
{ {
int a[30][4][5]; int a[30][4][5];
const auto av = as_multi_span(a); const auto av = as_multi_span(a);
const auto sub = av.section({15, 0, 0}, gsl::index<3>{2, 2, 2}); const auto sub = av.section({15, 0, 0}, gsl::index<3>{2, 2, 2});
const auto subsub = sub.section({1, 0, 0}, gsl::index<3>{1, 1, 1}); const auto subsub = sub.section({1, 0, 0}, gsl::index<3>{1, 1, 1});
(void)subsub; (void) subsub;
} }
TEST(span_section) TEST(span_section)
@ -51,13 +56,13 @@ SUITE(strided_span_tests)
std::iota(begin(data), end(data), 0); std::iota(begin(data), end(data), 0);
const multi_span<int, 5, 10> av = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>()); const multi_span<int, 5, 10> av = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>());
const strided_span<int, 2> av_section_1 = av.section({ 1, 2 }, { 3, 4 }); const strided_span<int, 2> av_section_1 = av.section({1, 2}, {3, 4});
CHECK((av_section_1[{0, 0}] == 12)); CHECK((av_section_1[{0, 0}] == 12));
CHECK((av_section_1[{0, 1}] == 13)); CHECK((av_section_1[{0, 1}] == 13));
CHECK((av_section_1[{1, 0}] == 22)); CHECK((av_section_1[{1, 0}] == 22));
CHECK((av_section_1[{2, 3}] == 35)); CHECK((av_section_1[{2, 3}] == 35));
const strided_span<int, 2> av_section_2 = av_section_1.section({ 1, 2 }, { 2,2 }); const strided_span<int, 2> av_section_2 = av_section_1.section({1, 2}, {2, 2});
CHECK((av_section_2[{0, 0}] == 24)); CHECK((av_section_2[{0, 0}] == 24));
CHECK((av_section_2[{0, 1}] == 25)); CHECK((av_section_2[{0, 1}] == 25));
CHECK((av_section_2[{1, 0}] == 34)); CHECK((av_section_2[{1, 0}] == 34));
@ -67,188 +72,197 @@ SUITE(strided_span_tests)
{ {
// Check stride constructor // Check stride constructor
{ {
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
const int carr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; const int carr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
strided_span<int, 1> sav1{ arr, {{9}, {1}} }; // T -> T strided_span<int, 1> sav1{arr, {{9}, {1}}}; // T -> T
CHECK(sav1.bounds().index_bounds() == index<1>{ 9 }); CHECK(sav1.bounds().index_bounds() == index<1>{9});
CHECK(sav1.bounds().stride() == 1); CHECK(sav1.bounds().stride() == 1);
CHECK(sav1[0] == 1 && sav1[8] == 9); CHECK(sav1[0] == 1 && sav1[8] == 9);
strided_span<const int, 1> sav2{carr, {{4}, {2}}}; // const T -> const T
strided_span<const int, 1> sav2{ carr, {{ 4 }, { 2 }} }; // const T -> const T CHECK(sav2.bounds().index_bounds() == index<1>{4});
CHECK(sav2.bounds().index_bounds() == index<1>{ 4 });
CHECK(sav2.bounds().strides() == index<1>{2}); CHECK(sav2.bounds().strides() == index<1>{2});
CHECK(sav2[0] == 1 && sav2[3] == 7); CHECK(sav2[0] == 1 && sav2[3] == 7);
strided_span<int, 2> sav3{ arr, {{ 2, 2 },{ 6, 2 }} }; // T -> const T strided_span<int, 2> sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T
CHECK((sav3.bounds().index_bounds() == index<2>{ 2, 2 })); CHECK((sav3.bounds().index_bounds() == index<2>{2, 2}));
CHECK((sav3.bounds().strides() == index<2>{ 6, 2 })); CHECK((sav3.bounds().strides() == index<2>{6, 2}));
CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7)); CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7));
} }
// Check multi_span constructor // Check multi_span constructor
{ {
int arr[] = { 1, 2 }; int arr[] = {1, 2};
// From non-cv-qualified source // From non-cv-qualified source
{ {
const multi_span<int> src = arr; const multi_span<int> src = arr;
strided_span<int, 1> sav{ src, {2, 1} }; strided_span<int, 1> sav{src, {2, 1}};
CHECK(sav.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav.bounds().index_bounds() == index<1>{2});
CHECK(sav.bounds().strides() == index<1>{ 1 }); CHECK(sav.bounds().strides() == index<1>{1});
CHECK(sav[1] == 2); CHECK(sav[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
//strided_span<const int, 1> sav_c{ {src}, {2, 1} }; // strided_span<const int, 1> sav_c{ {src}, {2, 1} };
strided_span<const int, 1> sav_c{ multi_span<const int>{src}, strided_bounds<1>{2, 1} }; strided_span<const int, 1> sav_c{multi_span<const int>{src},
strided_bounds<1>{2, 1}};
#else #else
strided_span<const int, 1> sav_c{ multi_span<const int>{src}, strided_bounds<1>{2, 1} }; strided_span<const int, 1> sav_c{multi_span<const int>{src},
strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_c.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav_c.bounds().index_bounds() == index<1>{2});
CHECK(sav_c.bounds().strides() == index<1>{ 1 }); CHECK(sav_c.bounds().strides() == index<1>{1});
CHECK(sav_c[1] == 2); CHECK(sav_c[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
strided_span<volatile int, 1> sav_v{ src, {2, 1} }; strided_span<volatile int, 1> sav_v{src, {2, 1}};
#else #else
strided_span<volatile int, 1> sav_v{ multi_span<volatile int>{src}, strided_bounds<1>{2, 1} }; strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src},
strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_v.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav_v.bounds().index_bounds() == index<1>{2});
CHECK(sav_v.bounds().strides() == index<1>{ 1 }); CHECK(sav_v.bounds().strides() == index<1>{1});
CHECK(sav_v[1] == 2); CHECK(sav_v[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{ src, {2, 1} }; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
#else #else
strided_span<const volatile int, 1> sav_cv{ multi_span<const volatile int>{src}, strided_bounds<1>{2, 1} }; strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav_cv.bounds().index_bounds() == index<1>{2});
CHECK(sav_cv.bounds().strides() == index<1>{ 1 }); CHECK(sav_cv.bounds().strides() == index<1>{1});
CHECK(sav_cv[1] == 2); CHECK(sav_cv[1] == 2);
} }
// From const-qualified source // From const-qualified source
{ {
const multi_span<const int> src{ arr }; const multi_span<const int> src{arr};
strided_span<const int, 1> sav_c{ src, {2, 1} }; strided_span<const int, 1> sav_c{src, {2, 1}};
CHECK(sav_c.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav_c.bounds().index_bounds() == index<1>{2});
CHECK(sav_c.bounds().strides() == index<1>{ 1 }); CHECK(sav_c.bounds().strides() == index<1>{1});
CHECK(sav_c[1] == 2); CHECK(sav_c[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{ src, {2, 1} }; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
#else #else
strided_span<const volatile int, 1> sav_cv{ multi_span<const volatile int>{src}, strided_bounds<1>{2, 1} }; strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav_cv.bounds().index_bounds() == index<1>{2});
CHECK(sav_cv.bounds().strides() == index<1>{ 1 }); CHECK(sav_cv.bounds().strides() == index<1>{1});
CHECK(sav_cv[1] == 2); CHECK(sav_cv[1] == 2);
} }
// From volatile-qualified source // From volatile-qualified source
{ {
const multi_span<volatile int> src{ arr }; const multi_span<volatile int> src{arr};
strided_span<volatile int, 1> sav_v{ src, {2, 1} }; strided_span<volatile int, 1> sav_v{src, {2, 1}};
CHECK(sav_v.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav_v.bounds().index_bounds() == index<1>{2});
CHECK(sav_v.bounds().strides() == index<1>{ 1 }); CHECK(sav_v.bounds().strides() == index<1>{1});
CHECK(sav_v[1] == 2); CHECK(sav_v[1] == 2);
#if _MSC_VER > 1800 #if _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{ src, {2, 1} }; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
#else #else
strided_span<const volatile int, 1> sav_cv{ multi_span<const volatile int>{src}, strided_bounds<1>{2, 1} }; strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav_cv.bounds().index_bounds() == index<1>{2});
CHECK(sav_cv.bounds().strides() == index<1>{ 1 }); CHECK(sav_cv.bounds().strides() == index<1>{1});
CHECK(sav_cv[1] == 2); CHECK(sav_cv[1] == 2);
} }
// From cv-qualified source // From cv-qualified source
{ {
const multi_span<const volatile int> src{ arr }; const multi_span<const volatile int> src{arr};
strided_span<const volatile int, 1> sav_cv{ src, {2, 1} }; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
CHECK(sav_cv.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav_cv.bounds().index_bounds() == index<1>{2});
CHECK(sav_cv.bounds().strides() == index<1>{ 1 }); CHECK(sav_cv.bounds().strides() == index<1>{1});
CHECK(sav_cv[1] == 2); CHECK(sav_cv[1] == 2);
} }
} }
// Check const-casting constructor // Check const-casting constructor
{ {
int arr[2] = { 4, 5 }; int arr[2] = {4, 5};
const multi_span<int, 2> av(arr, 2); const multi_span<int, 2> av(arr, 2);
multi_span<const int, 2> av2{ av }; multi_span<const int, 2> av2{av};
CHECK(av2[1] == 5); CHECK(av2[1] == 5);
static_assert(std::is_convertible<const multi_span<int, 2>, multi_span<const int, 2>>::value, "ctor is not implicit!"); static_assert(
std::is_convertible<const multi_span<int, 2>, multi_span<const int, 2>>::value,
"ctor is not implicit!");
const strided_span<int, 1> src{ arr, {2, 1} }; const strided_span<int, 1> src{arr, {2, 1}};
strided_span<const int, 1> sav{ src }; strided_span<const int, 1> sav{src};
CHECK(sav.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav.bounds().index_bounds() == index<1>{2});
CHECK(sav.bounds().stride() == 1); CHECK(sav.bounds().stride() == 1);
CHECK(sav[1] == 5); CHECK(sav[1] == 5);
static_assert(std::is_convertible<const strided_span<int, 1>, strided_span<const int, 1>>::value, "ctor is not implicit!"); static_assert(
std::is_convertible<const strided_span<int, 1>, strided_span<const int, 1>>::value,
"ctor is not implicit!");
} }
// Check copy constructor // Check copy constructor
{ {
int arr1[2] = { 3, 4 }; int arr1[2] = {3, 4};
const strided_span<int, 1> src1{ arr1, {2, 1} }; const strided_span<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> sav1{ src1 }; strided_span<int, 1> sav1{src1};
CHECK(sav1.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav1.bounds().index_bounds() == index<1>{2});
CHECK(sav1.bounds().stride() == 1); CHECK(sav1.bounds().stride() == 1);
CHECK(sav1[0] == 3); CHECK(sav1[0] == 3);
int arr2[6] = { 1, 2, 3, 4, 5, 6 }; int arr2[6] = {1, 2, 3, 4, 5, 6};
const strided_span<const int, 2> src2{ arr2, {{ 3, 2 }, { 2, 1 }} }; const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
strided_span<const int, 2> sav2{ src2 }; strided_span<const int, 2> sav2{src2};
CHECK((sav2.bounds().index_bounds() == index<2>{ 3, 2 })); CHECK((sav2.bounds().index_bounds() == index<2>{3, 2}));
CHECK((sav2.bounds().strides() == index<2>{ 2, 1 })); CHECK((sav2.bounds().strides() == index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5)); CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5));
} }
// Check const-casting assignment operator // Check const-casting assignment operator
{ {
int arr1[2] = { 1, 2 }; int arr1[2] = {1, 2};
int arr2[6] = { 3, 4, 5, 6, 7, 8 }; int arr2[6] = {3, 4, 5, 6, 7, 8};
const strided_span<int, 1> src{ arr1, {{2}, {1}} }; const strided_span<int, 1> src{arr1, {{2}, {1}}};
strided_span<const int, 1> sav{ arr2, {{3}, {2}} }; strided_span<const int, 1> sav{arr2, {{3}, {2}}};
strided_span<const int, 1>& sav_ref = (sav = src); strided_span<const int, 1>& sav_ref = (sav = src);
CHECK(sav.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav.bounds().index_bounds() == index<1>{2});
CHECK(sav.bounds().strides() == index<1>{ 1 }); CHECK(sav.bounds().strides() == index<1>{1});
CHECK(sav[0] == 1); CHECK(sav[0] == 1);
CHECK(&sav_ref == &sav); CHECK(&sav_ref == &sav);
} }
// Check copy assignment operator // Check copy assignment operator
{ {
int arr1[2] = { 3, 4 }; int arr1[2] = {3, 4};
int arr1b[1] = { 0 }; int arr1b[1] = {0};
const strided_span<int, 1> src1{ arr1, {2, 1} }; const strided_span<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> sav1{ arr1b, {1, 1} }; strided_span<int, 1> sav1{arr1b, {1, 1}};
strided_span<int, 1>& sav1_ref = (sav1 = src1); strided_span<int, 1>& sav1_ref = (sav1 = src1);
CHECK(sav1.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav1.bounds().index_bounds() == index<1>{2});
CHECK(sav1.bounds().strides() == index<1>{ 1 }); CHECK(sav1.bounds().strides() == index<1>{1});
CHECK(sav1[0] == 3); CHECK(sav1[0] == 3);
CHECK(&sav1_ref == &sav1); CHECK(&sav1_ref == &sav1);
const int arr2[6] = { 1, 2, 3, 4, 5, 6 }; const int arr2[6] = {1, 2, 3, 4, 5, 6};
const int arr2b[1] = { 0 }; const int arr2b[1] = {0};
const strided_span<const int, 2> src2{ arr2, {{ 3, 2 },{ 2, 1 }} }; const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
strided_span<const int, 2> sav2{ arr2b, {{ 1, 1 },{ 1, 1 }} }; strided_span<const int, 2> sav2{arr2b, {{1, 1}, {1, 1}}};
strided_span<const int, 2>& sav2_ref = (sav2 = src2); strided_span<const int, 2>& sav2_ref = (sav2 = src2);
CHECK((sav2.bounds().index_bounds() == index<2>{ 3, 2 })); CHECK((sav2.bounds().index_bounds() == index<2>{3, 2}));
CHECK((sav2.bounds().strides() == index<2>{ 2, 1 })); CHECK((sav2.bounds().strides() == index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5)); CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5));
CHECK(&sav2_ref == &sav2); CHECK(&sav2_ref == &sav2);
} }
@ -258,13 +272,15 @@ SUITE(strided_span_tests)
{ {
std::vector<int> data(5 * 10); std::vector<int> data(5 * 10);
std::iota(begin(data), end(data), 0); std::iota(begin(data), end(data), 0);
const multi_span<int, 5, 10> src = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>()); const multi_span<int, 5, 10> src =
as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>());
const strided_span<int, 2> sav{ src, {{5, 10}, {10, 1}} }; const strided_span<int, 2> sav{src, {{5, 10}, {10, 1}}};
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
const strided_span<const int, 2> csav{ {src},{ { 5, 10 },{ 10, 1 } } }; const strided_span<const int, 2> csav{{src}, {{5, 10}, {10, 1}}};
#endif #endif
const strided_span<const int, 2> csav{ multi_span<const int, 5, 10>{ src }, { { 5, 10 },{ 10, 1 } } }; const strided_span<const int, 2> csav{multi_span<const int, 5, 10>{src},
{{5, 10}, {10, 1}}};
strided_span<int, 1> sav_sl = sav[2]; strided_span<int, 1> sav_sl = sav[2];
CHECK(sav_sl[0] == 20); CHECK(sav_sl[0] == 20);
@ -284,12 +300,8 @@ SUITE(strided_span_tests)
// use cases, such as column-major multidimensional array // use cases, such as column-major multidimensional array
// (aka. "FORTRAN" layout). // (aka. "FORTRAN" layout).
int cm_array[3 * 5] = { int cm_array[3 * 5] = {1, 4, 7, 10, 13, 2, 5, 8, 11, 14, 3, 6, 9, 12, 15};
1, 4, 7, 10, 13, strided_span<int, 2> cm_sav{cm_array, {{5, 3}, {1, 5}}};
2, 5, 8, 11, 14,
3, 6, 9, 12, 15
};
strided_span<int, 2> cm_sav{ cm_array, {{ 5, 3 },{ 1, 5 }} };
// Accessing elements // Accessing elements
CHECK((cm_sav[{0, 0}] == 1)); CHECK((cm_sav[{0, 0}] == 1));
@ -305,7 +317,7 @@ SUITE(strided_span_tests)
CHECK(cm_sl[2] == 12); CHECK(cm_sl[2] == 12);
// Section // Section
strided_span<int, 2> cm_sec = cm_sav.section( { 2, 1 }, { 3, 2 }); strided_span<int, 2> cm_sec = cm_sav.section({2, 1}, {3, 2});
CHECK((cm_sec.bounds().index_bounds() == index<2>{3, 2})); CHECK((cm_sec.bounds().index_bounds() == index<2>{3, 2}));
CHECK((cm_sec[{0, 0}] == 8)); CHECK((cm_sec[{0, 0}] == 8));
@ -316,7 +328,7 @@ SUITE(strided_span_tests)
TEST(strided_span_bounds) TEST(strided_span_bounds)
{ {
int arr[] = { 0, 1, 2, 3 }; int arr[] = {0, 1, 2, 3};
multi_span<int> av(arr); multi_span<int> av(arr);
{ {
@ -335,7 +347,7 @@ SUITE(strided_span_tests)
{ {
// zero stride // zero stride
strided_span<int, 1> sav{ av,{ { 4 },{} } }; strided_span<int, 1> sav{av, {{4}, {}}};
CHECK(sav[0] == 0); CHECK(sav[0] == 0);
CHECK(sav[3] == 0); CHECK(sav[3] == 0);
CHECK_THROW(sav[4], fail_fast); CHECK_THROW(sav[4], fail_fast);
@ -343,36 +355,36 @@ SUITE(strided_span_tests)
{ {
// zero extent // zero extent
strided_span<int, 1> sav{ av,{ {},{ 1 } } }; strided_span<int, 1> sav{av, {{}, {1}}};
CHECK_THROW(sav[0], fail_fast); CHECK_THROW(sav[0], fail_fast);
} }
{ {
// zero extent and stride // zero extent and stride
strided_span<int, 1> sav{ av,{ {},{} } }; strided_span<int, 1> sav{av, {{}, {}}};
CHECK_THROW(sav[0], fail_fast); CHECK_THROW(sav[0], fail_fast);
} }
{ {
// strided array ctor with matching strided bounds // strided array ctor with matching strided bounds
strided_span<int, 1> sav{ arr,{ 4, 1 } }; strided_span<int, 1> sav{arr, {4, 1}};
CHECK(sav.bounds().index_bounds() == index<1>{ 4 }); CHECK(sav.bounds().index_bounds() == index<1>{4});
CHECK(sav[3] == 3); CHECK(sav[3] == 3);
CHECK_THROW(sav[4], fail_fast); CHECK_THROW(sav[4], fail_fast);
} }
{ {
// strided array ctor with smaller strided bounds // strided array ctor with smaller strided bounds
strided_span<int, 1> sav{ arr,{ 2, 1 } }; strided_span<int, 1> sav{arr, {2, 1}};
CHECK(sav.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav.bounds().index_bounds() == index<1>{2});
CHECK(sav[1] == 1); CHECK(sav[1] == 1);
CHECK_THROW(sav[2], fail_fast); CHECK_THROW(sav[2], fail_fast);
} }
{ {
// strided array ctor with fitting irregular bounds // strided array ctor with fitting irregular bounds
strided_span<int, 1> sav{ arr,{ 2, 3 } }; strided_span<int, 1> sav{arr, {2, 3}};
CHECK(sav.bounds().index_bounds() == index<1>{ 2 }); CHECK(sav.bounds().index_bounds() == index<1>{2});
CHECK(sav[0] == 0); CHECK(sav[0] == 0);
CHECK(sav[1] == 3); CHECK(sav[1] == 3);
CHECK_THROW(sav[2], fail_fast); CHECK_THROW(sav[2], fail_fast);
@ -380,68 +392,69 @@ SUITE(strided_span_tests)
{ {
// bounds cross data boundaries - from static arrays // bounds cross data boundaries - from static arrays
CHECK_THROW((strided_span<int, 1> { arr, { 3, 2 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{arr, {3, 2}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { arr, { 3, 3 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{arr, {3, 3}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { arr, { 4, 5 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{arr, {4, 5}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { arr, { 5, 1 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{arr, {5, 1}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { arr, { 5, 5 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{arr, {5, 5}}), fail_fast);
} }
{ {
// bounds cross data boundaries - from array view // bounds cross data boundaries - from array view
CHECK_THROW((strided_span<int, 1> { av, { 3, 2 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av, {3, 2}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av, { 3, 3 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av, {3, 3}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av, { 4, 5 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av, {4, 5}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av, { 5, 1 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av, {5, 1}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av, { 5, 5 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av, {5, 5}}), fail_fast);
} }
{ {
// bounds cross data boundaries - from dynamic arrays // bounds cross data boundaries - from dynamic arrays
CHECK_THROW((strided_span<int, 1> { av.data(), 4, { 3, 2 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av.data(), 4, {3, 2}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av.data(), 4, { 3, 3 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av.data(), 4, {3, 3}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av.data(), 4, { 4, 5 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av.data(), 4, {4, 5}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av.data(), 4, { 5, 1 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av.data(), 4, {5, 1}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av.data(), 4, { 5, 5 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av.data(), 4, {5, 5}}), fail_fast);
CHECK_THROW((strided_span<int, 1> { av.data(), 2, { 2, 2 } }), fail_fast); CHECK_THROW((strided_span<int, 1>{av.data(), 2, {2, 2}}), fail_fast);
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
strided_span<int, 1> sav0{ av.data(), { 3, 2 } }; strided_span<int, 1> sav0{av.data(), {3, 2}};
strided_span<int, 1> sav1{ arr, { 1 } }; strided_span<int, 1> sav1{arr, {1}};
strided_span<int, 1> sav2{ arr, { 1,1,1 } }; strided_span<int, 1> sav2{arr, {1, 1, 1}};
strided_span<int, 1> sav3{ av, { 1 } }; strided_span<int, 1> sav3{av, {1}};
strided_span<int, 1> sav4{ av, { 1,1,1 } }; strided_span<int, 1> sav4{av, {1, 1, 1}};
strided_span<int, 2> sav5{ av.as_multi_span(dim<2>(), dim<2>()), { 1 } }; strided_span<int, 2> sav5{av.as_multi_span(dim<2>(), dim<2>()), {1}};
strided_span<int, 2> sav6{ av.as_multi_span(dim<2>(), dim<2>()), { 1,1,1 } }; strided_span<int, 2> sav6{av.as_multi_span(dim<2>(), dim<2>()), {1, 1, 1}};
strided_span<int, 2> sav7{ av.as_multi_span(dim<2>(), dim<2>()), { { 1,1 },{ 1,1 },{ 1,1 } } }; strided_span<int, 2> sav7{av.as_multi_span(dim<2>(), dim<2>()),
{{1, 1}, {1, 1}, {1, 1}}};
index<1> index{ 0, 1 }; index<1> index{0, 1};
strided_span<int, 1> sav8{ arr,{ 1,{ 1,1 } } }; strided_span<int, 1> sav8{arr, {1, {1, 1}}};
strided_span<int, 1> sav9{ arr,{ { 1,1 },{ 1,1 } } }; strided_span<int, 1> sav9{arr, {{1, 1}, {1, 1}}};
strided_span<int, 1> sav10{ av,{ 1,{ 1,1 } } }; strided_span<int, 1> sav10{av, {1, {1, 1}}};
strided_span<int, 1> sav11{ av,{ { 1,1 },{ 1,1 } } }; strided_span<int, 1> sav11{av, {{1, 1}, {1, 1}}};
strided_span<int, 2> sav12{ av.as_multi_span(dim<2>(), dim<2>()),{ { 1 },{ 1 } } }; strided_span<int, 2> sav12{av.as_multi_span(dim<2>(), dim<2>()), {{1}, {1}}};
strided_span<int, 2> sav13{ av.as_multi_span(dim<2>(), dim<2>()),{ { 1 },{ 1,1,1 } } }; strided_span<int, 2> sav13{av.as_multi_span(dim<2>(), dim<2>()), {{1}, {1, 1, 1}}};
strided_span<int, 2> sav14{ av.as_multi_span(dim<2>(), dim<2>()),{ { 1,1,1 },{ 1 } } }; strided_span<int, 2> sav14{av.as_multi_span(dim<2>(), dim<2>()), {{1, 1, 1}, {1}}};
} }
#endif #endif
} }
TEST(strided_span_type_conversion) TEST(strided_span_type_conversion)
{ {
int arr[] = { 0, 1, 2, 3 }; int arr[] = {0, 1, 2, 3};
multi_span<int> av(arr); multi_span<int> av(arr);
{ {
strided_span<int, 1> sav{ av.data(), av.size(), { av.size() / 2, 2 } }; strided_span<int, 1> sav{av.data(), av.size(), {av.size() / 2, 2}};
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
strided_span<long, 1> lsav1 = sav.as_strided_span<long, 1>(); strided_span<long, 1> lsav1 = sav.as_strided_span<long, 1>();
#endif #endif
} }
{ {
strided_span<int, 1> sav{ av, { av.size() / 2, 2 } }; strided_span<int, 1> sav{av, {av.size() / 2, 2}};
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
strided_span<long, 1> lsav1 = sav.as_strided_span<long, 1>(); strided_span<long, 1> lsav1 = sav.as_strided_span<long, 1>();
#endif #endif
@ -451,8 +464,8 @@ SUITE(strided_span_tests)
// retype strided array with regular strides - from raw data // retype strided array with regular strides - from raw data
{ {
strided_bounds<2> bounds{ { 2, bytes.size() / 4 }, { bytes.size() / 2, 1 } }; strided_bounds<2> bounds{{2, bytes.size() / 4}, {bytes.size() / 2, 1}};
strided_span<const byte, 2> sav2{ bytes.data(), bytes.size(), bounds }; strided_span<const byte, 2> sav2{bytes.data(), bytes.size(), bounds};
strided_span<const int, 2> sav3 = sav2.as_strided_span<const int>(); strided_span<const int, 2> sav3 = sav2.as_strided_span<const int>();
CHECK(sav3[0][0] == 0); CHECK(sav3[0][0] == 0);
CHECK(sav3[1][0] == 2); CHECK(sav3[1][0] == 2);
@ -462,9 +475,10 @@ SUITE(strided_span_tests)
// retype strided array with regular strides - from multi_span // retype strided array with regular strides - from multi_span
{ {
strided_bounds<2> bounds{ { 2, bytes.size() / 4 }, { bytes.size() / 2, 1 } }; strided_bounds<2> bounds{{2, bytes.size() / 4}, {bytes.size() / 2, 1}};
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); multi_span<const byte, 2, dynamic_range> bytes2 =
strided_span<const byte, 2> sav2{ bytes2, bounds }; as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds};
strided_span<int, 2> sav3 = sav2.as_strided_span<int>(); strided_span<int, 2> sav3 = sav2.as_strided_span<int>();
CHECK(sav3[0][0] == 0); CHECK(sav3[0][0] == 0);
CHECK(sav3[1][0] == 2); CHECK(sav3[1][0] == 2);
@ -474,47 +488,53 @@ SUITE(strided_span_tests)
// retype strided array with not enough elements - last dimension of the array is too small // retype strided array with not enough elements - last dimension of the array is too small
{ {
strided_bounds<2> bounds{ { 4,2 },{ 4, 1 } }; strided_bounds<2> bounds{{4, 2}, {4, 1}};
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); multi_span<const byte, 2, dynamic_range> bytes2 =
strided_span<const byte, 2> sav2{ bytes2, bounds }; as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds};
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast); CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
} }
// retype strided array with not enough elements - strides are too small // retype strided array with not enough elements - strides are too small
{ {
strided_bounds<2> bounds{ { 4,2 },{ 2, 1 } }; strided_bounds<2> bounds{{4, 2}, {2, 1}};
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); multi_span<const byte, 2, dynamic_range> bytes2 =
strided_span<const byte, 2> sav2{ bytes2, bounds }; as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds};
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast); CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
} }
// retype strided array with not enough elements - last dimension does not divide by the new typesize // retype strided array with not enough elements - last dimension does not divide by the new
// typesize
{ {
strided_bounds<2> bounds{ { 2,6 },{ 4, 1 } }; strided_bounds<2> bounds{{2, 6}, {4, 1}};
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); multi_span<const byte, 2, dynamic_range> bytes2 =
strided_span<const byte, 2> sav2{ bytes2, bounds }; as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds};
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast); CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
} }
// retype strided array with not enough elements - strides does not divide by the new typesize // retype strided array with not enough elements - strides does not divide by the new
// typesize
{ {
strided_bounds<2> bounds{ { 2, 1 },{ 6, 1 } }; strided_bounds<2> bounds{{2, 1}, {6, 1}};
multi_span<const byte, 2, dynamic_range> bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); multi_span<const byte, 2, dynamic_range> bytes2 =
strided_span<const byte, 2> sav2{ bytes2, bounds }; as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds};
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast); CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
} }
// retype strided array with irregular strides - from raw data // retype strided array with irregular strides - from raw data
{ {
strided_bounds<1> bounds{ bytes.size() / 2, 2 }; strided_bounds<1> bounds{bytes.size() / 2, 2};
strided_span<const byte, 1> sav2{ bytes.data(), bytes.size(), bounds }; strided_span<const byte, 1> sav2{bytes.data(), bytes.size(), bounds};
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast); CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
} }
// retype strided array with irregular strides - from multi_span // retype strided array with irregular strides - from multi_span
{ {
strided_bounds<1> bounds{ bytes.size() / 2, 2 }; strided_bounds<1> bounds{bytes.size() / 2, 2};
strided_span<const byte, 1> sav2{ bytes, bounds }; strided_span<const byte, 1> sav2{bytes, bounds};
CHECK_THROW(sav2.as_strided_span<int>(), fail_fast); CHECK_THROW(sav2.as_strided_span<int>(), fail_fast);
} }
} }
@ -523,31 +543,29 @@ SUITE(strided_span_tests)
{ {
{ {
multi_span<int, 0> empty_av(nullptr); multi_span<int, 0> empty_av(nullptr);
strided_span<int, 1> empty_sav{ empty_av, { 0, 1 } }; strided_span<int, 1> empty_sav{empty_av, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == index<1>{ 0 }); CHECK(empty_sav.bounds().index_bounds() == index<1>{0});
CHECK_THROW(empty_sav[0], fail_fast); CHECK_THROW(empty_sav[0], fail_fast);
CHECK_THROW(empty_sav.begin()[0], fail_fast); CHECK_THROW(empty_sav.begin()[0], fail_fast);
CHECK_THROW(empty_sav.cbegin()[0], fail_fast); CHECK_THROW(empty_sav.cbegin()[0], fail_fast);
for (const auto& v : empty_sav) for (const auto& v : empty_sav) {
{ (void) v;
(void)v;
CHECK(false); CHECK(false);
} }
} }
{ {
strided_span<int, 1> empty_sav{ nullptr, 0, { 0, 1 } }; strided_span<int, 1> empty_sav{nullptr, 0, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == index<1>{ 0 }); CHECK(empty_sav.bounds().index_bounds() == index<1>{0});
CHECK_THROW(empty_sav[0], fail_fast); CHECK_THROW(empty_sav[0], fail_fast);
CHECK_THROW(empty_sav.begin()[0], fail_fast); CHECK_THROW(empty_sav.begin()[0], fail_fast);
CHECK_THROW(empty_sav.cbegin()[0], fail_fast); CHECK_THROW(empty_sav.cbegin()[0], fail_fast);
for (const auto& v : empty_sav) for (const auto& v : empty_sav) {
{ (void) v;
(void)v;
CHECK(false); CHECK(false);
} }
} }
@ -561,20 +579,18 @@ SUITE(strided_span_tests)
#if _MSC_VER > 1800 #if _MSC_VER > 1800
auto bounds = strided_bounds<1>({length}, {2}); auto bounds = strided_bounds<1>({length}, {2});
#else #else
auto bounds = strided_bounds<1>(index<1>{ length }, index<1>{ 2 }); auto bounds = strided_bounds<1>(index<1>{length}, index<1>{2});
#endif #endif
strided_span<int, 1> strided(&av.data()[1], av.size() - 1, bounds); strided_span<int, 1> strided(&av.data()[1], av.size() - 1, bounds);
CHECK(strided.size() == length); CHECK(strided.size() == length);
CHECK(strided.bounds().index_bounds()[0] == length); CHECK(strided.bounds().index_bounds()[0] == length);
for (auto i = 0; i < strided.size(); ++i) for (auto i = 0; i < strided.size(); ++i) {
{
CHECK(strided[i] == av[2 * i + 1]); CHECK(strided[i] == av[2 * i + 1]);
} }
int idx = 0; int idx = 0;
for (auto num : strided) for (auto num : strided) {
{
CHECK(num == av[2 * idx + 1]); CHECK(num == av[2 * idx + 1]);
idx++; idx++;
} }
@ -582,7 +598,7 @@ SUITE(strided_span_tests)
TEST(strided_span_section_iteration) TEST(strided_span_section_iteration)
{ {
int arr[8] = {4,0,5,1,6,2,7,3}; int arr[8] = {4, 0, 5, 1, 6, 2, 7, 3};
// static bounds // static bounds
{ {
@ -600,8 +616,7 @@ SUITE(strided_span_tests)
TEST(dynamic_strided_span_section_iteration) TEST(dynamic_strided_span_section_iteration)
{ {
auto arr = new int[8]; auto arr = new int[8];
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i) {
{
arr[2 * i] = 4 + i; arr[2 * i] = 4 + i;
arr[2 * i + 1] = i; arr[2 * i + 1] = i;
} }
@ -614,29 +629,25 @@ SUITE(strided_span_tests)
void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_range> av) void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_range> av)
{ {
const int expected[6] = {2,3,10,11,18,19}; const int expected[6] = {2, 3, 10, 11, 18, 19};
auto section = av.section({0,1,0}, {3,1,2}); auto section = av.section({0, 1, 0}, {3, 1, 2});
for (auto i = 0; i < section.extent<0>(); ++i) for (auto i = 0; i < section.extent<0>(); ++i) {
{
for (auto j = 0; j < section.extent<1>(); ++j) for (auto j = 0; j < section.extent<1>(); ++j)
for (auto k = 0; k < section.extent<2>(); ++k) for (auto k = 0; k < section.extent<2>(); ++k) {
{ auto idx = index<3>{i, j, k}; // avoid braces in the CHECK macro
auto idx = index<3>{i,j,k}; // avoid braces in the CHECK macro
CHECK(section[idx] == expected[2 * i + 2 * j + k]); CHECK(section[idx] == expected[2 * i + 2 * j + k]);
} }
} }
for (auto i = 0; i < section.extent<0>(); ++i) for (auto i = 0; i < section.extent<0>(); ++i) {
{
for (auto j = 0; j < section.extent<1>(); ++j) for (auto j = 0; j < section.extent<1>(); ++j)
for (auto k = 0; k < section.extent<2>(); ++k) for (auto k = 0; k < section.extent<2>(); ++k)
CHECK(section[i][j][k] == expected[2 * i + 2 * j + k]); CHECK(section[i][j][k] == expected[2 * i + 2 * j + k]);
} }
int i = 0; int i = 0;
for (const auto num : section) for (const auto num : section) {
{
CHECK(num == expected[i]); CHECK(num == expected[i]);
i++; i++;
} }
@ -645,11 +656,9 @@ SUITE(strided_span_tests)
TEST(strided_span_section_iteration_3d) TEST(strided_span_section_iteration_3d)
{ {
int arr[3][4][2]{}; int arr[3][4][2]{};
for (auto i = 0; i < 3; ++i) for (auto i = 0; i < 3; ++i) {
{
for (auto j = 0; j < 4; ++j) for (auto j = 0; j < 4; ++j)
for (auto k = 0; k < 2; ++k) for (auto k = 0; k < 2; ++k) arr[i][j][k] = 8 * i + 2 * j + k;
arr[i][j][k] = 8 * i + 2 * j + k;
} }
{ {
@ -664,8 +673,7 @@ SUITE(strided_span_tests)
const auto size = height * width; const auto size = height * width;
auto arr = new int[static_cast<std::size_t>(size)]; auto arr = new int[static_cast<std::size_t>(size)];
for (auto i = 0; i < size; ++i) for (auto i = 0; i < size; ++i) {
{
arr[i] = i; arr[i] = i;
} }
@ -695,9 +703,14 @@ SUITE(strided_span_tests)
{ {
// get an multi_span of 'c' values from the list of X's // get an multi_span of 'c' values from the list of X's
struct X { int a; int b; int c; }; struct X
{
int a;
int b;
int c;
};
X arr[4] = {{0,1,2},{3,4,5},{6,7,8},{9,10,11}}; X arr[4] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}};
int s = sizeof(int) / sizeof(byte); int s = sizeof(int) / sizeof(byte);
auto d2 = 3 * s; auto d2 = 3 * s;
@ -710,9 +723,11 @@ SUITE(strided_span_tests)
CHECK(av.bounds().index_bounds()[1] == 12); CHECK(av.bounds().index_bounds()[1] == 12);
// get the last 4 columns // get the last 4 columns
auto section = av.section({0, 2 * s}, {4, s}); // { { arr[0].c[0], arr[0].c[1], arr[0].c[2], arr[0].c[3] } , { arr[1].c[0], ... } , ... } auto section = av.section({0, 2 * s}, {4, s}); // { { arr[0].c[0], arr[0].c[1], arr[0].c[2],
// arr[0].c[3] } , { arr[1].c[0], ... } , ...
// }
// convert to array 4x1 array of integers // convert to array 4x1 array of integers
auto cs = section.as_strided_span<int>(); // { { arr[0].c }, {arr[1].c } , ... } auto cs = section.as_strided_span<int>(); // { { arr[0].c }, {arr[1].c } , ... }
CHECK(cs.bounds().index_bounds()[0] == 4); CHECK(cs.bounds().index_bounds()[0] == 4);
@ -720,9 +735,8 @@ SUITE(strided_span_tests)
// transpose to 1x4 array // transpose to 1x4 array
strided_bounds<2> reverse_bounds{ strided_bounds<2> reverse_bounds{
{cs.bounds().index_bounds()[1] , cs.bounds().index_bounds()[0]}, {cs.bounds().index_bounds()[1], cs.bounds().index_bounds()[0]},
{cs.bounds().strides()[1], cs.bounds().strides()[0]} {cs.bounds().strides()[1], cs.bounds().strides()[0]}};
};
strided_span<int, 2> transposed{cs.data(), cs.bounds().total_size(), reverse_bounds}; strided_span<int, 2> transposed{cs.data(), cs.bounds().total_size(), reverse_bounds};
@ -733,16 +747,11 @@ SUITE(strided_span_tests)
CHECK_THROW(result.bounds().index_bounds()[1], fail_fast); CHECK_THROW(result.bounds().index_bounds()[1], fail_fast);
int i = 0; int i = 0;
for (auto& num : result) for (auto& num : result) {
{
CHECK(num == arr[i].c); CHECK(num == arr[i].c);
i++; i++;
} }
} }
} }
int main(int, const char *[]) int main(int, const char* []) { return UnitTest::RunAllTests(); }
{
return UnitTest::RunAllTests();
}

View File

@ -15,16 +15,17 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <cstdlib>
#include <gsl/string_span>
#include <gsl/gsl> //owner #include <gsl/gsl> //owner
#include <vector> #include <gsl/string_span>
#include <cstdlib>
#include <map> #include <map>
#include <vector>
using namespace std; using namespace std;
using namespace gsl; using namespace gsl;
SUITE(string_span_tests) SUITE(string_span_tests)
{ {
@ -48,7 +49,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<>::index_type>(vec.size())); CHECK(v.length() == static_cast<string_span<>::index_type>(vec.size()));
} }
@ -96,7 +97,7 @@ SUITE(string_span_tests)
{ {
char stack_string[] = "Hello"; char stack_string[] = "Hello";
cstring_span<> v = ensure_z(stack_string); cstring_span<> v = ensure_z(stack_string);
(void)v; (void) v;
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
string_span<> v2 = v; string_span<> v2 = v;
string_span<> v3 = "Hello"; string_span<> v3 = "Hello";
@ -117,12 +118,13 @@ SUITE(string_span_tests)
TEST(TestToBasicString) TEST(TestToBasicString)
{ {
auto s = gsl::to_basic_string<char,std::char_traits<char>,::std::allocator<char>>(cstring_span<>{}); auto s = gsl::to_basic_string<char, std::char_traits<char>, ::std::allocator<char>>(
cstring_span<>{});
CHECK(s.length() == 0); CHECK(s.length() == 0);
char stack_string[] = "Hello"; char stack_string[] = "Hello";
cstring_span<> v = ensure_z(stack_string); cstring_span<> v = ensure_z(stack_string);
auto s2 = gsl::to_basic_string<char,std::char_traits<char>,::std::allocator<char>>(v); auto s2 = gsl::to_basic_string<char, std::char_traits<char>, ::std::allocator<char>>(v);
CHECK(static_cast<cstring_span<>::index_type>(s2.length()) == v.length()); CHECK(static_cast<cstring_span<>::index_type>(s2.length()) == v.length());
CHECK(s2.length() == 5); CHECK(s2.length() == 5);
} }
@ -150,12 +152,12 @@ SUITE(string_span_tests)
{ {
cstring_span<> span = "Hello"; cstring_span<> span = "Hello";
const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; const char ar[] = {'H', 'e', 'l', 'l', 'o'};
const char ar1[] = "Hello"; const char ar1[] = "Hello";
const char ar2[10] = "Hello"; const char ar2[10] = "Hello";
const char* ptr = "Hello"; const char* ptr = "Hello";
const std::string str = "Hello"; const std::string str = "Hello";
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
gsl::span<const char> sp = ensure_z("Hello"); gsl::span<const char> sp = ensure_z("Hello");
// comparison to literal // comparison to literal
@ -187,7 +189,7 @@ SUITE(string_span_tests)
} }
{ {
char ar[] = { 'H', 'e', 'l', 'l', 'o' }; char ar[] = {'H', 'e', 'l', 'l', 'o'};
string_span<> span = ar; string_span<> span = ar;
@ -195,7 +197,7 @@ SUITE(string_span_tests)
char ar2[10] = "Hello"; char ar2[10] = "Hello";
char* ptr = ar; char* ptr = ar;
std::string str = "Hello"; std::string str = "Hello";
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
gsl::span<char> sp = ensure_z(ar1); gsl::span<char> sp = ensure_z(ar1);
// comparison to static array with no null termination // comparison to static array with no null termination
@ -223,13 +225,12 @@ SUITE(string_span_tests)
CHECK(span == span); CHECK(span == span);
} }
{ {
const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; const char ar[] = {'H', 'e', 'l', 'l', 'o'};
const char ar1[] = "Hello"; const char ar1[] = "Hello";
const char ar2[10] = "Hello"; const char ar2[10] = "Hello";
const std::string str = "Hello"; const std::string str = "Hello";
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const gsl::span<const char> sp = ensure_z("Hello"); const gsl::span<const char> sp = ensure_z("Hello");
cstring_span<> span = "Hello"; cstring_span<> span = "Hello";
@ -261,13 +262,13 @@ SUITE(string_span_tests)
// const span, non-const other type // const span, non-const other type
char _ar[] = { 'H', 'e', 'l', 'l', 'o' }; char _ar[] = {'H', 'e', 'l', 'l', 'o'};
char _ar1[] = "Hello"; char _ar1[] = "Hello";
char _ar2[10] = "Hello"; char _ar2[10] = "Hello";
char* _ptr = _ar; char* _ptr = _ar;
std::string _str = "Hello"; std::string _str = "Hello";
std::vector<char> _vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> _vec = {'H', 'e', 'l', 'l', 'o'};
gsl::span<char> _sp{ _ar, 5 }; gsl::span<char> _sp{_ar, 5};
CHECK(span == _ar); CHECK(span == _ar);
CHECK(span == _ar1); CHECK(span == _ar1);
@ -289,7 +290,7 @@ SUITE(string_span_tests)
CHECK(_vec == span); CHECK(_vec == span);
CHECK(_sp == span); CHECK(_sp == span);
string_span<> _span{ _ptr, 5 }; string_span<> _span{_ptr, 5};
// non-const span, non-const other type // non-const span, non-const other type
@ -344,7 +345,7 @@ SUITE(string_span_tests)
} }
{ {
std::vector<char> str1 = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> str1 = {'H', 'e', 'l', 'l', 'o'};
cstring_span<> span1 = str1; cstring_span<> span1 = str1;
std::vector<char> str2 = std::move(str1); std::vector<char> str2 = std::move(str1);
cstring_span<> span2 = str2; cstring_span<> span2 = str2;
@ -359,12 +360,12 @@ SUITE(string_span_tests)
{ {
cstring_span<> span = "Hello"; cstring_span<> span = "Hello";
const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; const char ar[] = {'H', 'e', 'l', 'l', 'o'};
const char ar1[] = "Hello"; const char ar1[] = "Hello";
const char ar2[10] = "Hello"; const char ar2[10] = "Hello";
const char* ptr = "Hello"; const char* ptr = "Hello";
const std::string str = "Hello"; const std::string str = "Hello";
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
// comparison to literal // comparison to literal
CHECK(span < cstring_span<>("Helloo")); CHECK(span < cstring_span<>("Helloo"));
@ -390,7 +391,7 @@ SUITE(string_span_tests)
} }
{ {
char ar[] = { 'H', 'e', 'l', 'l', 'o' }; char ar[] = {'H', 'e', 'l', 'l', 'o'};
string_span<> span = ar; string_span<> span = ar;
@ -401,8 +402,7 @@ SUITE(string_span_tests)
char ar2[10] = "Hello"; char ar2[10] = "Hello";
char* ptr = ar; char* ptr = ar;
std::string str = "Hello"; std::string str = "Hello";
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
// comparison to static array with no null termination // comparison to static array with no null termination
CHECK(span <= string_span<>(ar)); CHECK(span <= string_span<>(ar));
@ -466,7 +466,7 @@ SUITE(string_span_tests)
CHECK(span.length() == 6); CHECK(span.length() == 6);
} }
// from const span of a final extent to non-const string_span // from const span of a final extent to non-const string_span
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
span<const char, 6> sp = "Hello"; span<const char, 6> sp = "Hello";
@ -475,7 +475,7 @@ SUITE(string_span_tests)
} }
#endif #endif
// from string temporary // from string temporary
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
cstring_span<> span = std::string("Hello"); cstring_span<> span = std::string("Hello");
@ -502,14 +502,14 @@ SUITE(string_span_tests)
// from const static array // from const static array
{ {
const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; const char ar[] = {'H', 'e', 'l', 'l', 'o'};
cstring_span<> span = ar; cstring_span<> span = ar;
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
// from non-const static array // from non-const static array
{ {
char ar[] = { 'H', 'e', 'l', 'l', 'o' }; char ar[] = {'H', 'e', 'l', 'l', 'o'};
cstring_span<> span = ar; cstring_span<> span = ar;
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
@ -517,37 +517,37 @@ SUITE(string_span_tests)
// from const ptr and length // from const ptr and length
{ {
const char* ptr = "Hello"; const char* ptr = "Hello";
cstring_span<> span{ ptr, 5 }; cstring_span<> span{ptr, 5};
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
// from const ptr and length, include 0 // from const ptr and length, include 0
{ {
const char* ptr = "Hello"; const char* ptr = "Hello";
cstring_span<> span{ ptr, 6 }; cstring_span<> span{ptr, 6};
CHECK(span.length() == 6); CHECK(span.length() == 6);
} }
// from const ptr and length, 0 inside // from const ptr and length, 0 inside
{ {
const char* ptr = "He\0lo"; const char* ptr = "He\0lo";
cstring_span<> span{ ptr, 5 }; cstring_span<> span{ptr, 5};
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
// from non-const ptr and length // from non-const ptr and length
{ {
char ar[] = { 'H', 'e', 'l', 'l', 'o' }; char ar[] = {'H', 'e', 'l', 'l', 'o'};
char* ptr = ar; char* ptr = ar;
cstring_span<> span{ ptr, 5 }; cstring_span<> span{ptr, 5};
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
// from non-const ptr and length, 0 inside // from non-const ptr and length, 0 inside
{ {
char ar[] = { 'H', 'e', '\0', 'l', 'o' }; char ar[] = {'H', 'e', '\0', 'l', 'o'};
char* ptr = ar; char* ptr = ar;
cstring_span<> span{ ptr, 5 }; cstring_span<> span{ptr, 5};
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
@ -567,21 +567,21 @@ SUITE(string_span_tests)
// from const vector // from const vector
{ {
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const cstring_span<> span = vec; const cstring_span<> span = vec;
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
// from non-const vector // from non-const vector
{ {
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const cstring_span<> span = vec; const cstring_span<> span = vec;
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
// from const span // from const span
{ {
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const span<const char> inner = vec; const span<const char> inner = vec;
const cstring_span<> span = inner; const cstring_span<> span = inner;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -589,7 +589,7 @@ SUITE(string_span_tests)
// from non-const span // from non-const span
{ {
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const span<char> inner = vec; const span<char> inner = vec;
const cstring_span<> span = inner; const cstring_span<> span = inner;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -597,7 +597,7 @@ SUITE(string_span_tests)
// from const string_span // from const string_span
{ {
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const cstring_span<> tmp = vec; const cstring_span<> tmp = vec;
const cstring_span<> span = tmp; const cstring_span<> span = tmp;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -605,7 +605,7 @@ SUITE(string_span_tests)
// from non-const string_span // from non-const string_span
{ {
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
string_span<> tmp = vec; string_span<> tmp = vec;
cstring_span<> span = tmp; cstring_span<> span = tmp;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -623,7 +623,7 @@ SUITE(string_span_tests)
// from const static array // from const static array
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
const char ar[] = { 'H', 'e', 'l', 'l', 'o' }; const char ar[] = {'H', 'e', 'l', 'l', 'o'};
string_span<> span = ar; string_span<> span = ar;
CHECK(span.length() == 5); CHECK(span.length() == 5);
#endif #endif
@ -631,7 +631,7 @@ SUITE(string_span_tests)
// from non-const static array // from non-const static array
{ {
char ar[] = { 'H', 'e', 'l', 'l', 'o' }; char ar[] = {'H', 'e', 'l', 'l', 'o'};
string_span<> span = ar; string_span<> span = ar;
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
@ -640,16 +640,16 @@ SUITE(string_span_tests)
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
const char* ptr = "Hello"; const char* ptr = "Hello";
string_span<> span{ ptr, 5 }; string_span<> span{ptr, 5};
CHECK(span.length() == 5); CHECK(span.length() == 5);
#endif #endif
} }
// from non-const ptr and length // from non-const ptr and length
{ {
char ar[] = { 'H', 'e', 'l', 'l', 'o' }; char ar[] = {'H', 'e', 'l', 'l', 'o'};
char* ptr = ar; char* ptr = ar;
string_span<> span{ ptr, 5 }; string_span<> span{ptr, 5};
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
@ -672,7 +672,7 @@ SUITE(string_span_tests)
// from const vector // from const vector
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
string_span<> span = vec; string_span<> span = vec;
CHECK(span.length() == 5); CHECK(span.length() == 5);
#endif #endif
@ -680,7 +680,7 @@ SUITE(string_span_tests)
// from non-const vector // from non-const vector
{ {
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
string_span<> span = vec; string_span<> span = vec;
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
@ -688,7 +688,7 @@ SUITE(string_span_tests)
// from const span // from const span
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const span<const char> inner = vec; const span<const char> inner = vec;
string_span<> span = inner; string_span<> span = inner;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -697,7 +697,7 @@ SUITE(string_span_tests)
// from non-const span // from non-const span
{ {
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
span<char> inner = vec; span<char> inner = vec;
string_span<> span = inner; string_span<> span = inner;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -706,7 +706,7 @@ SUITE(string_span_tests)
// from non-const span of non-const data from const vector // from non-const span of non-const data from const vector
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const span<char> inner = vec; const span<char> inner = vec;
string_span<> span = inner; string_span<> span = inner;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -716,7 +716,7 @@ SUITE(string_span_tests)
// from const string_span // from const string_span
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
cstring_span<> tmp = vec; cstring_span<> tmp = vec;
string_span<> span = tmp; string_span<> span = tmp;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -725,7 +725,7 @@ SUITE(string_span_tests)
// from non-const string_span // from non-const string_span
{ {
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const string_span<> tmp = vec; const string_span<> tmp = vec;
const string_span<> span = tmp; const string_span<> span = tmp;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -734,7 +734,7 @@ SUITE(string_span_tests)
// from non-const string_span from const vector // from non-const string_span from const vector
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; const std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
string_span<> tmp = vec; string_span<> tmp = vec;
string_span<> span = tmp; string_span<> span = tmp;
CHECK(span.length() == 5); CHECK(span.length() == 5);
@ -743,24 +743,29 @@ SUITE(string_span_tests)
// from const string_span of non-const data // from const string_span of non-const data
{ {
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
const string_span<> tmp = vec; const string_span<> tmp = vec;
const string_span<> span = tmp; const string_span<> span = tmp;
CHECK(span.length() == 5); CHECK(span.length() == 5);
} }
} }
template<typename T> template <typename T>
T move_wrapper(T&& t) T move_wrapper(T && t)
{ {
return std::move(t); return std::move(t);
} }
template <class T> template <class T>
T create() { return T{}; } T create()
{
return T{};
}
template <class T> template <class T>
void use(basic_string_span<T, gsl::dynamic_extent>) {} void use(basic_string_span<T, gsl::dynamic_extent>)
{
}
TEST(MoveConstructors) TEST(MoveConstructors)
{ {
@ -817,14 +822,14 @@ SUITE(string_span_tests)
// move container // move container
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
string_span<> span = std::move(vec); string_span<> span = std::move(vec);
CHECK(span.length() == 5); CHECK(span.length() == 5);
#endif #endif
} }
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' }; std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};
string_span<> span = move_wrapper<std::vector<char>>(std::move(vec)); string_span<> span = move_wrapper<std::vector<char>>(std::move(vec));
CHECK(span.length() == 5); CHECK(span.length() == 5);
#endif #endif
@ -840,7 +845,7 @@ SUITE(string_span_tests)
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
cstring_span<> span = "Hello"; cstring_span<> span = "Hello";
cwstring_span<> wspan{ span }; cwstring_span<> wspan{span};
CHECK(wspan.length() == 5); CHECK(wspan.length() == 5);
#endif #endif
} }
@ -850,8 +855,7 @@ SUITE(string_span_tests)
Expects(span.size() > 1); Expects(span.size() > 1);
int last = 0; int last = 0;
if (span.size() > 4) if (span.size() > 4) {
{
span[0] = 't'; span[0] = 't';
span[1] = 'm'; span[1] = 'm';
span[2] = 'p'; span[2] = 'p';
@ -860,7 +864,7 @@ SUITE(string_span_tests)
span[last] = '\0'; span[last] = '\0';
auto ret = span.subspan(0, 4); auto ret = span.subspan(0, 4);
return{ ret }; return {ret};
} }
TEST(zstring) TEST(zstring)
@ -871,7 +875,7 @@ SUITE(string_span_tests)
char buf[1]; char buf[1];
buf[0] = '\0'; buf[0] = '\0';
zstring_span<> zspan({ buf, 1 }); zstring_span<> zspan({buf, 1});
CHECK(strlen(zspan.assume_z()) == 0); CHECK(strlen(zspan.assume_z()) == 0);
CHECK(zspan.as_string_span().size() == 0); CHECK(zspan.as_string_span().size() == 0);
@ -883,7 +887,7 @@ SUITE(string_span_tests)
char buf[1]; char buf[1];
buf[0] = 'a'; buf[0] = 'a';
auto workaround_macro = [&]() { zstring_span<> zspan({ buf, 1 }); }; auto workaround_macro = [&]() { zstring_span<> zspan({buf, 1}); };
CHECK_THROW(workaround_macro(), fail_fast); CHECK_THROW(workaround_macro(), fail_fast);
} }
@ -891,15 +895,13 @@ SUITE(string_span_tests)
{ {
char buf[10]; char buf[10];
auto name = CreateTempName({ buf, 10 }); auto name = CreateTempName({buf, 10});
if (!name.empty()) if (!name.empty()) {
{
czstring<> str = name.assume_z(); czstring<> str = name.assume_z();
CHECK(strlen(str) == 3); CHECK(strlen(str) == 3);
CHECK(*(str+3) == '\0'); CHECK(*(str + 3) == '\0');
} }
} }
} }
cwzstring_span<> CreateTempNameW(wstring_span<> span) cwzstring_span<> CreateTempNameW(wstring_span<> span)
@ -907,8 +909,7 @@ SUITE(string_span_tests)
Expects(span.size() > 1); Expects(span.size() > 1);
int last = 0; int last = 0;
if (span.size() > 4) if (span.size() > 4) {
{
span[0] = L't'; span[0] = L't';
span[1] = L'm'; span[1] = L'm';
span[2] = L'p'; span[2] = L'p';
@ -917,7 +918,7 @@ SUITE(string_span_tests)
span[last] = L'\0'; span[last] = L'\0';
auto ret = span.subspan(0, 4); auto ret = span.subspan(0, 4);
return{ ret }; return {ret};
} }
TEST(wzstring) TEST(wzstring)
@ -928,7 +929,7 @@ SUITE(string_span_tests)
wchar_t buf[1]; wchar_t buf[1];
buf[0] = L'\0'; buf[0] = L'\0';
wzstring_span<> zspan({ buf, 1 }); wzstring_span<> zspan({buf, 1});
CHECK(wcsnlen(zspan.assume_z(), 1) == 0); CHECK(wcsnlen(zspan.assume_z(), 1) == 0);
CHECK(zspan.as_string_span().size() == 0); CHECK(zspan.as_string_span().size() == 0);
@ -940,7 +941,7 @@ SUITE(string_span_tests)
wchar_t buf[1]; wchar_t buf[1];
buf[0] = L'a'; buf[0] = L'a';
const auto workaround_macro = [&]() { wzstring_span<> zspan({ buf, 1 }); }; const auto workaround_macro = [&]() { wzstring_span<> zspan({buf, 1}); };
CHECK_THROW(workaround_macro(), fail_fast); CHECK_THROW(workaround_macro(), fail_fast);
} }
@ -948,9 +949,8 @@ SUITE(string_span_tests)
{ {
wchar_t buf[10]; wchar_t buf[10];
const auto name = CreateTempNameW({ buf, 10 }); const auto name = CreateTempNameW({buf, 10});
if (!name.empty()) if (!name.empty()) {
{
cwzstring<> str = name.assume_z(); cwzstring<> str = name.assume_z();
CHECK(wcsnlen(str, 10) == 3); CHECK(wcsnlen(str, 10) == 3);
CHECK(*(str + 3) == L'\0'); CHECK(*(str + 3) == L'\0');
@ -960,13 +960,10 @@ SUITE(string_span_tests)
TEST(Issue305) TEST(Issue305)
{ {
std::map<gsl::cstring_span<>, int> foo = { { "foo", 0 },{ "bar", 1 } }; std::map<gsl::cstring_span<>, int> foo = {{"foo", 0}, {"bar", 1}};
CHECK(foo["foo"] == 0); CHECK(foo["foo"] == 0);
CHECK(foo["bar"] == 1); CHECK(foo["bar"] == 1);
} }
} }
int main(int, const char *[]) int main(int, const char* []) { return UnitTest::RunAllTests(); }
{
return UnitTest::RunAllTests();
}

View File

@ -15,23 +15,22 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <UnitTest++/UnitTest++.h> #include <UnitTest++/UnitTest++.h>
#include <gsl/gsl> #include <gsl/gsl>
#include <functional> #include <functional>
using namespace gsl; using namespace gsl;
SUITE(utils_tests) SUITE(utils_tests)
{ {
void f(int& i) void f(int& i) { i += 1; }
{
i += 1;
}
TEST(finally_lambda) TEST(finally_lambda)
{ {
int i = 0; int i = 0;
{ {
auto _ = finally([&]() {f(i);}); auto _ = finally([&]() { f(i); });
CHECK(i == 0); CHECK(i == 0);
} }
CHECK(i == 1); CHECK(i == 1);
@ -41,7 +40,7 @@ SUITE(utils_tests)
{ {
int i = 0; int i = 0;
{ {
auto _1 = finally([&]() {f(i);}); auto _1 = finally([&]() { f(i); });
{ {
auto _2 = std::move(_1); auto _2 = std::move(_1);
CHECK(i == 0); CHECK(i == 0);
@ -113,7 +112,4 @@ SUITE(utils_tests)
} }
} }
int main(int, const char *[]) int main(int, const char* []) { return UnitTest::RunAllTests(); }
{
return UnitTest::RunAllTests();
}