1
#ifndef CHILON_APPEND_HPP
2
#define CHILON_APPEND_HPP
3
4
#include <chilon/meta/return.hpp>
5
6
#include <vector>
7
#include <unordered_map>
8
#include <type_traits>
9
10
namespace chilon {
11
12
namespace detail { struct appendable {}; }
13
14
template <class K>
15
struct key_collision {
16
    key_collision(K const& key) : key_(key) {};
17
    K const key_;
18
};
19
20
template <class K>
21
void throw_key_collision(K const& key) {
22
    throw key_collision<K>(key);
23
}
24
25
template <class T, class U>
26
static inline
27
CHILON_RETURN_REQUIRE(void, std::is_base_of<detail::appendable, T>)
28
append(T& src, U const& dest) {
29
    T::append_type::exec(src, dest);
30
}
31
32
template <class T, class U>
33
static inline
34
CHILON_RETURN_REQUIRE(void, std::is_base_of<detail::appendable, T>)
35
append(T& src, U&& dest) {
36
    T::append_type::exec(src, std::move(dest));
37
}
38
39
template <class T>
40
static inline void append(std::vector<T>& dest, std::vector<T> const& src) {
41
    for (auto i = src.begin(); i != src.end(); ++i) dest.push_back(*i);
42
}
43
44
template <class T>
45
static inline void append(std::vector<T>& dest, std::vector<T>&& src) {
46
    for (auto i = src.begin(); i != src.end(); ++i) dest.push_back(std::move(*i));
47
}
48
49
template <class T, class U>
50
static inline void append_map(T& t, U const& u) {
51
    for (auto it = u.begin(); it != u.end(); ++it) {
52
        if (! t.insert(*it).second)
53
            throw_key_collision(it->first);
54
    }
55
}
56
57
template <class T, class U>
58
static inline void append_map(T& t, U&& u) {
59
    for (auto it = u.begin(); it != u.end(); ++it) {
60
        if (! t.emplace(std::move(*it)).second)
61
            throw_key_collision(it->first);
62
    }
63
}
64
65
template <class U, class K, class V, class _H, class A>
66
static inline void append(std::unordered_map<K, V, _H, A>& t, U const& u) {
67
    append_map(t, u);
68
}
69
70
template <class U, class K, class V, class _H, class A>
71
static inline void append(std::unordered_map<K, V, _H, A>& t, U&& u) {
72
    append_map(t, u);
73
}
74
75
template <class T>
76
struct appendable : detail::appendable {
77
    typedef T append_type;
78
};
79
80
}
81
#endif