File: hashable_test.cpp

package info (click to toggle)
mapbox-variant 1.2.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,648 kB
  • sloc: cpp: 31,068; ansic: 959; python: 424; makefile: 145; objc: 59; sh: 36
file content (158 lines) | stat: -rw-r--r-- 3,048 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <cstddef>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <string>
#include <unordered_set>
#include <utility>

#include <mapbox/variant.hpp>

using namespace mapbox::util;

void test_singleton()
{
    using V = variant<int>;

    V singleton = 5;

    if (std::hash<V>{}(singleton) != std::hash<int>{}(5))
    {
        std::cerr << "Expected variant hash to be the same as hash of its value\n";
        std::exit(EXIT_FAILURE);
    }
}

void test_default_hashable()
{
    using V = variant<int, double, std::string>;

    V var;

    // Check int hashes
    var = 1;

    if (std::hash<V>{}(var) != std::hash<int>{}(1))
    {
        std::cerr << "Expected variant hash to be the same as hash of its value\n";
        std::exit(EXIT_FAILURE);
    }

    // Check double hashes
    var = 23.4;

    if (std::hash<V>{}(var) != std::hash<double>{}(23.4))
    {
        std::cerr << "Expected variant hash to be the same as hash of its value\n";
        std::exit(EXIT_FAILURE);
    }

    // Check string hashes
    var = std::string{"Hello, World!"};

    if (std::hash<V>{}(var) != std::hash<std::string>{}("Hello, World!"))
    {
        std::cerr << "Expected variant hash to be the same as hash of its value\n";
        std::exit(EXIT_FAILURE);
    }
}

struct Hashable
{
    static const constexpr auto const_hash = 5;
};

namespace std {
template <>
struct hash<Hashable>
{
    std::size_t operator()(const Hashable&) const noexcept
    {
        return Hashable::const_hash;
    }
};
}

void test_custom_hasher()
{
    using V = variant<int, Hashable, double>;

    V var;

    var = Hashable{};

    if (std::hash<V>{}(var) != Hashable::const_hash)
    {
        std::cerr << "Expected variant hash to be the same as hash of its value\n";
        std::exit(EXIT_FAILURE);
    }
}

void test_hashable_in_container()
{
    using V = variant<int, std::string, double>;

    // won't compile if V is not Hashable
    std::unordered_set<V> vs;

    vs.insert(1);
    vs.insert(2.3);
    vs.insert("4");
}

struct Empty
{
};

struct Node;

using Tree = variant<Empty, recursive_wrapper<Node>>;

struct Node
{
    Node(Tree left_, Tree right_) : left(std::move(left_)), right(std::move(right_)) {}

    Tree left = Empty{};
    Tree right = Empty{};
};

namespace std {
template <>
struct hash<Empty>
{
    std::size_t operator()(const Empty&) const noexcept
    {
        return 3;
    }
};

template <>
struct hash<Node>
{
    std::size_t operator()(const Node& n) const noexcept
    {
        return 5 + std::hash<Tree>{}(n.left) + std::hash<Tree>{}(n.right);
    }
};
}

void test_recursive_hashable()
{

    Tree tree = Node{Node{Empty{}, Empty{}}, Empty{}};

    if (std::hash<Tree>{}(tree) != ((5 + (5 + (3 + 3))) + 3))
    {
        std::cerr << "Expected variant hash to be the same as hash of its value\n";
        std::exit(EXIT_FAILURE);
    }
}

int main()
{
    test_singleton();
    test_default_hashable();
    test_custom_hasher();
    test_hashable_in_container();
    test_recursive_hashable();
}