mirror of https://github.com/procxx/kepka.git
				
				
				
			
		
			
				
	
	
		
			159 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
| #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();
 | |
| }
 |