1 // -*- C++ -*-
2 //===------------------------------ span ---------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===---------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10
11 // <span>
12
13 // template<class Container>
14 // constexpr span(Container& cont);
15 // template<class Container>
16 // constexpr span(const Container& cont);
17 //
18 // Remarks: These constructors shall not participate in overload resolution unless:
19 // — extent == dynamic_extent,
20 // — Container is not a specialization of span,
21 // — Container is not a specialization of array,
22 // — is_array_v<Container> is false,
23 // — data(cont) and size(cont) are both well-formed, and
24 // — remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[].
25 //
26
27 #include <span>
28 #include <cassert>
29 #include <deque>
30 #include <forward_list>
31 #include <list>
32 #include <vector>
33
34 #include "test_macros.h"
35
36 // Look ma - I'm a container!
37 template <typename T>
38 struct IsAContainer {
IsAContainerIsAContainer39 constexpr IsAContainer() : v_{} {}
sizeIsAContainer40 constexpr size_t size() const {return 1;}
dataIsAContainer41 constexpr T *data() {return &v_;}
dataIsAContainer42 constexpr const T *data() const {return &v_;}
43
getVIsAContainer44 constexpr const T *getV() const {return &v_;} // for checking
45 T v_;
46 };
47
48 template <typename T>
49 struct NotAContainerNoData {
sizeNotAContainerNoData50 size_t size() const {return 0;}
51 };
52
53 template <typename T>
54 struct NotAContainerNoSize {
dataNotAContainerNoSize55 const T *data() const {return nullptr;}
56 };
57
58 template <typename T>
59 struct NotAContainerPrivate {
60 private:
sizeNotAContainerPrivate61 size_t size() const {return 0;}
dataNotAContainerPrivate62 const T *data() const {return nullptr;}
63 };
64
65 template<class T, size_t extent, class container>
createImplicitSpan(container c)66 std::span<T, extent> createImplicitSpan(container c) {
67 return {c}; // expected-error {{chosen constructor is explicit in copy-initialization}}
68 }
69
main(int,char **)70 int main(int, char**)
71 {
72
73 // Making non-const spans from const sources (a temporary binds to `const &`)
74 {
75 std::span<int> s1{IsAContainer<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
76 std::span<int> s3{std::vector<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
77 }
78
79 // Missing size and/or data
80 {
81 std::span<const int> s1{NotAContainerNoData<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
82 std::span<const int> s3{NotAContainerNoSize<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
83 std::span<const int> s5{NotAContainerPrivate<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
84
85 // Again with the standard containers
86 std::span<const int> s11{std::deque<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
87 std::span<const int> s13{std::list<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
88 std::span<const int> s15{std::forward_list<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
89 }
90
91 // Not the same type
92 {
93 IsAContainer<int> c;
94 std::span<float> s1{c}; // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
95 }
96
97 // CV wrong
98 {
99 IsAContainer<const int> c;
100 IsAContainer<const volatile int> cv;
101 IsAContainer< volatile int> v;
102
103 std::span< int> s1{c}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
104 std::span< int> s2{v}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
105 std::span< int> s3{cv}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
106 std::span<const int> s4{v}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
107 std::span<const int> s5{cv}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
108 std::span< volatile int> s6{c}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
109 std::span< volatile int> s7{cv}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
110 }
111
112 // explicit constructor necessary
113 {
114 IsAContainer<int> c;
115 const IsAContainer<int> cc;
116
117 createImplicitSpan<int, 1>(c);
118 createImplicitSpan<int, 1>(cc);
119 }
120
121 return 0;
122 }
123