stl_output.h 5.27 KB
Newer Older
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
//
// Created by daleroux on 02/05/17.
//

#ifndef SPELL_QTL_STL_OUTPUT_H
#define SPELL_QTL_STL_OUTPUT_H

#include <iostream>
#include <string>

namespace output {
    template <typename CONTAINER>
    struct traits {
        static constexpr const char* prefix = "{";
        static constexpr const char* suffix = "}";
        static constexpr const char* value_prefix = "";
        static constexpr const char* value_suffix = "";
        static constexpr const char* key_prefix = "";
        static constexpr const char* key_suffix = ": ";
        static constexpr const char* separator = ", ";
    };

    template <typename _Stream, typename _Container>
    _Stream& output_value_container(_Stream& os, _Container&& container) {
        typedef traits<_Container> _Traits;
        auto beg = container.begin(), end = container.end();
        os << _Traits::prefix;
        if (beg != end) {
            os << (*beg);
            for (++beg; beg != end; ++beg) {
                os << _Traits::separator << (*beg);
            }
        }
        return os << _Traits::suffix;
    };

    namespace detail {
        template<typename T>
        struct has_const_iterator
        {
        private:
            typedef char                      yes;
            typedef struct { char array[2]; } no;

            template<typename C> static yes test(typename C::const_iterator*);
            template<typename C> static no  test(...);
        public:
            static const bool value = sizeof(test<T>(0)) == sizeof(yes);
            typedef T type;
        };

        template <typename T>
        struct has_begin_end
        {
            template<typename C> static char (&f(typename std::enable_if<
                    std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::begin)),
                            typename C::const_iterator(C::*)() const>::value, void>::type*))[1];

            template<typename C> static char (&f(...))[2];

            template<typename C> static char (&g(typename std::enable_if<
                    std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::end)),
                            typename C::const_iterator(C::*)() const>::value, void>::type*))[1];

            template<typename C> static char (&g(...))[2];

            static bool const beg_value = sizeof(f<T>(0)) == 1;
            static bool const end_value = sizeof(g<T>(0)) == 1;
        };

        template <>
        struct has_begin_end<std::string> {
            static bool const beg_value = false;
            static bool const end_value = false;
        };

        template<typename T>
        struct is_container
                : std::integral_constant<bool,
                                         has_const_iterator<T>::value
                                         && has_begin_end<T>::beg_value
                                         && has_begin_end<T>::end_value> {};
    }
}


template <typename C>
typename std::enable_if<output::detail::is_container<C>::value, std::ostream&>::type
operator << (std::ostream&& os, C&& v) { return output::output_value_container(os, v); }

template <typename C>
typename std::enable_if<output::detail::is_container<C>::value, std::ostream&>::type
operator << (std::ostream& os, C&& v) { return output::output_value_container(os, v); }

template <typename C>
typename std::enable_if<output::detail::is_container<C>::value, std::ostream&>::type
operator << (std::ostream&& os, const C& v) { return output::output_value_container(os, v); }

template <typename C>
typename std::enable_if<output::detail::is_container<C>::value, std::ostream&>::type
operator << (std::ostream& os, const C& v) { return output::output_value_container(os, v); }


template <typename A, typename B>
std::ostream&
operator << (std::ostream& os, std::pair<A, B>&& v)
{
    typedef output::traits<std::pair<A, B>> _Traits;
    return os << _Traits::key_prefix << v.first << _Traits::key_suffix << _Traits::value_prefix << v.second << _Traits::value_suffix;
}

template <typename A, typename B>
std::ostream&
operator << (std::ostream&& os, std::pair<A, B>&& v)
{
    typedef output::traits<std::pair<A, B>> _Traits;
    return os << _Traits::key_prefix << v.first << _Traits::key_suffix << _Traits::value_prefix << v.second << _Traits::value_suffix;
}

template <typename A, typename B>
std::ostream&
operator << (std::ostream& os, const std::pair<A, B>& v)
{
    typedef output::traits<std::pair<A, B>> _Traits;
    return os << _Traits::key_prefix << v.first << _Traits::key_suffix << _Traits::value_prefix << v.second << _Traits::value_suffix;
}

template <typename A, typename B>
std::ostream&
operator << (std::ostream&& os, const std::pair<A, B>& v)
{
    typedef output::traits<std::pair<A, B>> _Traits;
    return os << _Traits::key_prefix << v.first << _Traits::key_suffix << _Traits::value_prefix << v.second << _Traits::value_suffix;
}




//template <typename C>
//typename std::enable_if<output::detail::is_container<C>::value, std::ostream&>::type
//operator << (std::ostream& os, const C& v) { return output::output_value_container(os, v); }

//template <typename S, typename C>
//typename std::enable_if<output::detail::is_container<C>::value, std::ostream&>::type
//operator << (S&& os, const C& v) { return output::output_value_container(os, v); }

#endif //SPELL_QTL_STL_OUTPUT_H