Bitcoin Core 28.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
12namespace {
13struct Ignore
14{
15 template<typename T> Ignore(T&&) {}
16};
17template<typename T>
18bool Spannable(T&& value, decltype(Span{value})* enable = nullptr)
19{
20 return true;
21}
22bool 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
32struct SpannableYes
33{
34 int* data();
35 size_t size();
36};
37struct SpannableNo
38{
39 void* data();
40 size_t size();
41};
42#if defined(__clang__)
43# pragma clang diagnostic pop
44#endif
45} // namespace
46
47BOOST_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.
61BOOST_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_END()
#define BOOST_CHECK(expr)
Definition: object.cpp:17
BOOST_AUTO_TEST_CASE(span_constructor_sfinae)
Definition: span_tests.cpp:61