diff --git a/src/util/scoped_map.h b/src/util/scoped_map.h index 5f4316d69..9dfa9bb40 100644 --- a/src/util/scoped_map.h +++ b/src/util/scoped_map.h @@ -33,7 +33,16 @@ public: explicit scoped_map(size_type bucket_count = LEAN_SCOPED_MAP_INITIAL_BUCKET_SIZE, const Hash& hash = Hash(), const KeyEqual& equal = KeyEqual()): - m_map(bucket_count, hash, equal) {} + m_map(bucket_count, hash, equal) { + // the return type of Hash()(k) should be convertible to size_t + static_assert(std::is_convertible())(Key const &)>::type, + std::size_t>::value, + "The return type of hash function is not convertible to std::size_t"); + // the return type of KeyEqual()(k1, k2) should be bool + static_assert(std::is_same())(Key const &, Key const &)>::type, + bool>::value, + "The return type of KeyEqual()(k1, k2) is not bool"); + } void swap(scoped_map & other) { m_map.swap(other.m_map); diff --git a/src/util/scoped_set.h b/src/util/scoped_set.h index 22518bba6..9ec018e04 100644 --- a/src/util/scoped_set.h +++ b/src/util/scoped_set.h @@ -31,7 +31,16 @@ public: explicit scoped_set(size_type bucket_count = LEAN_SCOPED_SET_INITIAL_BUCKET_SIZE, const Hash& hash = Hash(), const KeyEqual& equal = KeyEqual()): - m_set(bucket_count, hash, equal) {} + m_set(bucket_count, hash, equal) { + // the return type of Hash()(k) should be convertible to size_t + static_assert(std::is_convertible())(Key const &)>::type, + std::size_t>::value, + "The return type of hash function is not convertible to std::size_t"); + // the return type of KeyEqual()(k1, k2) should be bool + static_assert(std::is_same())(Key const &, Key const &)>::type, + bool>::value, + "The return type of KeyEqual()(k1, k2) is not bool"); + } /** \brief Return the number of scopes. */ unsigned num_scopes() const { diff --git a/src/util/splay_map.h b/src/util/splay_map.h index cc6c1fdfe..c311dd6a3 100644 --- a/src/util/splay_map.h +++ b/src/util/splay_map.h @@ -22,8 +22,12 @@ class splay_map : public CMP { }; splay_tree m_map; public: - splay_map(CMP const & cmp = CMP()):m_map(entry_cmp(cmp)) {} - + splay_map(CMP const & cmp = CMP()):m_map(entry_cmp(cmp)) { + // the return type of CMP()(k1, k2) should be int + static_assert(std::is_same())(K const &, K const &)>::type, + int>::value, + "The return type of CMP()(k1, k2) is not int."); + } void swap(splay_map & m) { m_map.swap(m.m_map); } bool empty() const { return m_map.empty(); } void clear() { m_map.clear(); } @@ -60,12 +64,16 @@ public: template R fold(F f, R r) const { + static_assert(std::is_same::type, R>::value, + "fold: return type of f(k : K, t : T, r : R) is not R"); auto f_prime = [&](entry const & e, R r) -> R { return f(e.first, e.second, r); }; return m_map.fold(f_prime, r); } template void for_each(F f) const { + static_assert(std::is_same::type, void>::value, + "for_each: return type of f is not void"); auto f_prime = [&](entry const & e) { f(e.first, e.second); }; return m_map.for_each(f_prime); } @@ -94,10 +102,14 @@ splay_map erase(splay_map const & m, K const & k) { } template R fold(splay_map const & m, F f, R r) { + static_assert(std::is_same::type, R>::value, + "fold: return type of f(k : K, t : T, r : R) is not R"); return m.fold(f, r); } template void for_each(splay_map const & m, F f) { + static_assert(std::is_same::type, void>::value, + "for_each: return type of f is not void"); return m.for_each(f); } } diff --git a/src/util/splay_tree.h b/src/util/splay_tree.h index 7b5d5accb..8e2d96167 100644 --- a/src/util/splay_tree.h +++ b/src/util/splay_tree.h @@ -42,6 +42,10 @@ class splay_tree : public CMP { static void dec_ref(node * n) { if (n) n->dec_ref(); } explicit node(T const & v, node * left = nullptr, node * right = nullptr): m_left(left), m_right(right), m_value(v), m_rc(0) { + // the return type of CMP()(t1, 2) should be int + static_assert(std::is_same())(T const &, T const &)>::type, + int>::value, + "The return type of CMP()(t1, t2) is not int."); inc_ref(m_left); inc_ref(m_right); } @@ -289,6 +293,8 @@ class splay_tree : public CMP { template static R fold(node const * n, F & f, R r) { + static_assert(std::is_same::type, R>::value, + "fold: return type of f(t : T, r : R) is not R"); if (n) { r = fold(n->m_left, f, r); r = f(n->m_value, r); @@ -300,6 +306,8 @@ class splay_tree : public CMP { template static void for_each(node const * n, F & f) { + static_assert(std::is_same::type, void>::value, + "for_each: return type of f is not void"); if (n) { for_each(n->m_left, f); f(n->m_value); @@ -332,7 +340,7 @@ public: bool is_eqp(splay_tree const & t) const { return m_ptr == t.m_ptr; } /** \brief Return the size of the splay tree */ - unsigned size() const { return fold([](T const &, unsigned a) { return a + 1; }, 0); } + unsigned size() const { return fold([](T const &, unsigned a) { return a + 1; }, 0u); } /** \brief Insert \c v in this splay tree. */ void insert(T const & v) { @@ -425,6 +433,8 @@ public: */ template R fold(F f, R r) const { + static_assert(std::is_same::type, R>::value, + "fold: return type of f(t : T, r : R) is not R"); return fold(m_ptr, f, r); } @@ -433,6 +443,8 @@ public: */ template void for_each(F f) const { + static_assert(std::is_same::type, void>::value, + "for_each: return type of f is not void"); for_each(m_ptr, f); } }; @@ -442,10 +454,14 @@ template splay_tree erase(splay_tree & t, T const & v) { splay_tree r(t); r.erase(v); return r; } template R fold(splay_tree const & t, F f, R r) { + static_assert(std::is_same::type, R>::value, + "fold: return type of f(t : T, r : R) is not R"); return t.fold(f, r); } template void for_each(splay_tree const & t, F f) { + static_assert(std::is_same::type, void>::value, + "for_each: return type of f is not void"); return t.for_each(f); } }