1111#include < algorithm>
1212#include < cstdint>
1313#include < iostream>
14+ #include < ostream>
15+ #include < string>
1416#include < type_traits>
17+ #include < utility>
1518#include < vector>
1619
1720CPL_BEGIN
1821
22+ // ostream overloads for debugging output
23+ template <class First , class Second >
24+ std::ostream& operator <<(std::ostream& os, const std::pair<First, Second>& p) {
25+ return os << ' (' << p.first << " , " << p.second << ' )' ;
26+ }
27+
28+ template <typename Cont,
29+ class Valty = typename std::enable_if<!std::is_same<Cont, std::string>::value, typename Cont::value_type>::type>
30+ std::ostream& operator <<(std::ostream& os, const Cont& container) {
31+ os << ' {' ;
32+ auto it = container.begin ();
33+ auto end = container.end ();
34+
35+ if (it != end) {
36+ os << *it;
37+ ++it;
38+ }
39+
40+ for (; it != end; ++it) {
41+ os << " , " << *it;
42+ }
43+
44+ return os << ' }' ;
45+ }
46+
47+ // macros for debugging output
48+ #if DBG_MODE || CPL
49+ template <class ... Args>
50+ void dbg_out () {
51+ std::cerr << std::endl;
52+ }
53+
54+ template <class Head , class ... Tail>
55+ void dbg_out (Head&& head, Tail&&... tail) {
56+ std::cerr << ' ' << head;
57+ dbg_out (std::forward<Tail>(tail)...);
58+ }
59+
60+ #define test (...) std::cerr << " [" << #__VA_ARGS__ << " ]:" , dbg_out(__VA_ARGS__)
61+ #else // ^^^ DBG_MODE || CPL ^^^ / vvv !DBG_MODE && !CPL
62+ #define test (...)
63+ #endif // DBG_MODE || CPL
64+
1965template <typename ... Ts>
2066struct _Is_container_helper {};
2167
@@ -33,6 +79,49 @@ constexpr bool is_container = _Is_container<T>::value;
3379
3480#define CPL_IS_CONTAINER (T ) static_assert (is_container<T>, " Templated parameter is not a valid container." )
3581
82+ template <class FwdIter >
83+ const void output_container (FwdIter first, FwdIter last, const bool & space = true , const bool & new_line = true ) {
84+ for (; first != last; ++first) {
85+ std::cout << *first;
86+
87+ if (space && first != last - 1 ) {
88+ std::cout << ' ' ;
89+ }
90+ }
91+
92+ std::cout << (new_line ? ' \n ' : ' ' );
93+ }
94+
95+ template <typename Cont>
96+ const void output_container (const Cont& container, const bool & space = true , const bool & new_line = true ) {
97+ #if CPL
98+ CPL_IS_CONTAINER (Cont);
99+ #endif // CPL
100+ output_container (container.begin (), container.end (), space, new_line);
101+ }
102+
103+ template <class FwdIter >
104+ const void output_reverse_container (
105+ FwdIter first, FwdIter last, const bool & space = true , const bool & new_line = true ) {
106+ for (; first != last; ++first) {
107+ std::cout << *first;
108+
109+ if (space && first != last - 1 ) {
110+ std::cout << ' ' ;
111+ }
112+ }
113+
114+ std::cout << (new_line ? ' \n ' : ' ' );
115+ }
116+
117+ template <typename Cont>
118+ const void output_reverse_container (const Cont& container, const bool & space = true , const bool & new_line = true ) {
119+ #if CPL
120+ CPL_IS_CONTAINER (Cont);
121+ #endif // CPL
122+ output_reverse_container (container.rbegin (), container.rend (), space, new_line);
123+ }
124+
36125template <class ... Args>
37126auto alternating_insertion (Args&&... args) {
38127 // 3-arg -> Treat arguments as containers, e.g. (input1, input2, output)
0 commit comments