span_tests.cpp raw

   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()
  63