Bitcoin Core  27.99.0
P2P Digital Currency
span_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2023 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 {
13 struct Ignore
14 {
15  template<typename T> Ignore(T&&) {}
16 };
17 template<typename T>
18 bool Spannable(T&& value, decltype(Span{value})* enable = nullptr)
19 {
20  return true;
21 }
22 bool Spannable(Ignore)
23 {
24  return false;
25 }
26 
27 #if defined(__clang__)
28 # pragma clang diagnostic push
29 # pragma clang diagnostic ignored "-Wunneeded-member-function"
30 # pragma clang diagnostic ignored "-Wunused-member-function"
31 #endif
32 struct SpannableYes
33 {
34  int* data();
35  size_t size();
36 };
37 struct SpannableNo
38 {
39  void* data();
40  size_t size();
41 };
42 #if defined(__clang__)
43 # pragma clang diagnostic pop
44 #endif
45 } // namespace
46 
47 BOOST_AUTO_TEST_SUITE(span_tests)
48 
49 // Make sure template Span template deduction guides accurately enable calls to
50 // Span constructor overloads that work, and disable calls to constructor overloads that
51 // don't work. This makes it is possible to use the Span constructor in a SFINAE
52 // contexts like in the Spannable function above to detect whether types are or
53 // aren't compatible with Spans at compile time.
54 //
55 // Previously there was a bug where writing a SFINAE check for vector<bool> was
56 // not possible, because in libstdc++ vector<bool> has a data() member
57 // returning void*, and the Span template guide ignored the data() return value,
58 // so the template substitution would succeed, but the constructor would fail,
59 // resulting in a fatal compile error, rather than a SFINAE error that could be
60 // handled.
61 BOOST_AUTO_TEST_CASE(span_constructor_sfinae)
62 {
63  BOOST_CHECK(Spannable(std::vector<int>{}));
64  BOOST_CHECK(!Spannable(std::set<int>{}));
65  BOOST_CHECK(!Spannable(std::vector<bool>{}));
66  BOOST_CHECK(Spannable(std::array<int, 3>{}));
67  BOOST_CHECK(Spannable(Span<int>{}));
68  BOOST_CHECK(Spannable("char array"));
69  BOOST_CHECK(Spannable(SpannableYes{}));
70  BOOST_CHECK(!Spannable(SpannableNo{}));
71 }
72 
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:98
BOOST_AUTO_TEST_SUITE(cuckoocache_tests)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
#define BOOST_CHECK(expr)
Definition: object.cpp:17
BOOST_AUTO_TEST_CASE(span_constructor_sfinae)
Definition: span_tests.cpp:61