1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// <span>
// template<size_t N>
// constexpr span(element_type (&arr)[N]) noexcept;
//
// Remarks: These constructors shall not participate in overload resolution unless:
// - extent == dynamic_extent || N == extent is true, and
// - remove_pointer_t<decltype(data(arr))>(*)[] is convertible to ElementType(*)[].
//
#include <cassert>
#include <span>
#include <string>
#include <type_traits>
#include "test_macros.h"
void checkCV()
{
int arr[] = {1,2,3};
const int carr[] = {4,5,6};
volatile int varr[] = {7,8,9};
const volatile int cvarr[] = {1,3,5};
// Types the same (dynamic sized)
{
std::span< int> s1{ arr}; // a span< int> pointing at int.
std::span<const int> s2{ carr}; // a span<const int> pointing at const int.
std::span< volatile int> s3{ varr}; // a span< volatile int> pointing at volatile int.
std::span<const volatile int> s4{cvarr}; // a span<const volatile int> pointing at const volatile int.
assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
}
// Types the same (static sized)
{
std::span< int,3> s1{ arr}; // a span< int> pointing at int.
std::span<const int,3> s2{ carr}; // a span<const int> pointing at const int.
std::span< volatile int,3> s3{ varr}; // a span< volatile int> pointing at volatile int.
std::span<const volatile int,3> s4{cvarr}; // a span<const volatile int> pointing at const volatile int.
assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
}
// types different (dynamic sized)
{
std::span<const int> s1{ arr}; // a span<const int> pointing at int.
std::span< volatile int> s2{ arr}; // a span< volatile int> pointing at int.
std::span< volatile int> s3{ arr}; // a span< volatile int> pointing at const int.
std::span<const volatile int> s4{ arr}; // a span<const volatile int> pointing at int.
std::span<const volatile int> s5{carr}; // a span<const volatile int> pointing at const int.
std::span<const volatile int> s6{varr}; // a span<const volatile int> pointing at volatile int.
assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
}
// types different (static sized)
{
std::span<const int,3> s1{ arr}; // a span<const int> pointing at int.
std::span< volatile int,3> s2{ arr}; // a span< volatile int> pointing at int.
std::span< volatile int,3> s3{ arr}; // a span< volatile int> pointing at const int.
std::span<const volatile int,3> s4{ arr}; // a span<const volatile int> pointing at int.
std::span<const volatile int,3> s5{carr}; // a span<const volatile int> pointing at const int.
std::span<const volatile int,3> s6{varr}; // a span<const volatile int> pointing at volatile int.
assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
}
}
template<class T>
constexpr bool testSpan()
{
T val[2] = {};
ASSERT_NOEXCEPT(std::span<T>{val});
ASSERT_NOEXCEPT(std::span<T, 2>{val});
ASSERT_NOEXCEPT(std::span<const T>{val});
ASSERT_NOEXCEPT(std::span<const T, 2>{val});
std::span<T> s1 = val;
std::span<T, 2> s2 = val;
std::span<const T> s3 = val;
std::span<const T, 2> s4 = val;
assert(s1.data() == val && s1.size() == 2);
assert(s2.data() == val && s2.size() == 2);
assert(s3.data() == val && s3.size() == 2);
assert(s4.data() == val && s4.size() == 2);
std::span<const int> s5 = {{1,2}};
#if TEST_STD_VER >= 26
std::span<const int, 2> s6({1, 2});
#else
std::span<const int, 2> s6 = {{1,2}};
#endif
assert(s5.size() == 2); // and it dangles
assert(s6.size() == 2); // and it dangles
return true;
}
struct A {};
int main(int, char**)
{
testSpan<int>();
testSpan<double>();
testSpan<A>();
testSpan<std::string>();
static_assert(testSpan<int>());
static_assert(testSpan<double>());
static_assert(testSpan<A>());
checkCV();
// Size wrong
{
static_assert(!std::is_constructible<std::span<int, 2>, int (&)[3]>::value, "");
}
// Type wrong
{
static_assert(!std::is_constructible<std::span<float>, int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<float, 3>, int (&)[3]>::value, "");
}
// CV wrong (dynamically sized)
{
static_assert(!std::is_constructible<std::span<int>, const int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<int>, volatile int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<int>, const volatile int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<const int>, volatile int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<const int>, const volatile int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<volatile int>, const int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<volatile int>, const volatile int (&)[3]>::value, "");
}
// CV wrong (statically sized)
{
static_assert(!std::is_constructible<std::span<int, 3>, const int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<int, 3>, volatile int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<int, 3>, const volatile int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<const int, 3>, volatile int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<const int, 3>, const volatile int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<volatile int, 3>, const int (&)[3]>::value, "");
static_assert(!std::is_constructible<std::span<volatile int, 3>, const volatile int (&)[3]>::value, "");
}
return 0;
}
|