/ src / test / span_tests.cpp
span_tests.cpp
 1  // Copyright (c) 2023-present The Bitcoin Core developers
 2  // Distributed under the MIT software license, see the accompanying
 3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 4  
 5  #include <span.h>
 6  
 7  #include <boost/test/unit_test.hpp>
 8  #include <array>
 9  #include <set>
10  #include <vector>
11  
12  namespace spannable {
13  struct Ignore
14  {
15      template<typename T> Ignore(T&&) {}
16  };
17  template<typename T>
18  bool Spannable(T&& value, decltype(std::span{value})* enable = nullptr)
19  {
20      return true;
21  }
22  bool Spannable(Ignore)
23  {
24      return false;
25  }
26  
27  struct SpannableYes
28  {
29      int* data();
30      int* begin();
31      int* end();
32      size_t size();
33  };
34  struct SpannableNo
35  {
36      void data();
37      size_t size();
38  };
39  } // namespace spannable
40  
41  using namespace spannable;
42  
43  BOOST_AUTO_TEST_SUITE(span_tests)
44  
45  // Make sure template std::span template deduction guides accurately enable calls to
46  // std::span constructor overloads that work, and disable calls to constructor overloads that
47  // don't work. This makes it possible to use the std::span constructor in a SFINAE
48  // contexts like in the Spannable function above to detect whether types are or
49  // aren't compatible with std::span at compile time.
50  BOOST_AUTO_TEST_CASE(span_constructor_sfinae)
51  {
52      BOOST_CHECK(Spannable(std::vector<int>{}));
53      BOOST_CHECK(!Spannable(std::set<int>{}));
54      BOOST_CHECK(!Spannable(std::vector<bool>{}));
55      BOOST_CHECK(Spannable(std::array<int, 3>{}));
56      BOOST_CHECK(Spannable(std::span<int>{}));
57      BOOST_CHECK(Spannable("char array"));
58      BOOST_CHECK(Spannable(SpannableYes{}));
59      BOOST_CHECK(!Spannable(SpannableNo{}));
60  }
61  
62  BOOST_AUTO_TEST_SUITE_END()