IDS peak ICV v1.1.0
Loading...
Searching...
No Matches
peak_icv_printable.hpp
Go to the documentation of this file.
1
11#pragma once
12
13#include <type_traits>
14#include <algorithm>
15#include <ostream>
16#include <sstream>
17#include <string>
18#include <vector>
19
20namespace peak
21{
22namespace icv
23{
24namespace detail
25{
26
28{
29public:
30 explicit CommaSeperatedStream(std::ostream& os)
31 : m_os(os)
32 {}
33
34 template <typename Type>
35 CommaSeperatedStream& operator<<(const Type& value)
36 {
37 if (m_addDelimiter)
38 {
39 m_os << delimiter;
40 }
41 m_os << value;
42 m_addDelimiter = true;
43 return *this;
44 }
45
46 template <typename Type>
47 CommaSeperatedStream& operator<<(const std::vector<Type>& vector)
48 {
49 if (m_addDelimiter)
50 {
51 m_os << delimiter;
52 }
53
54 m_os << "{ ";
55 CommaSeperatedStream innerStream(m_os);
56 std::for_each(vector.begin(), vector.end(), [&](const auto& elem) {
57 innerStream << elem;
58 });
59 m_os << " }";
60
61 m_addDelimiter = true;
62 return *this;
63 }
64
65 CommaSeperatedStream& operator<<(std::ostream& (*manip)(std::ostream&))
66 {
67 m_addDelimiter = false;
68 m_os << delimiter;
69 m_os << manip;
70 return *this;
71 }
72
73private:
74 std::ostream& m_os;
75 bool m_addDelimiter = false;
76 constexpr static const char* delimiter = ", ";
77};
78
79// This is not real CRTP
80// NOLINTBEGIN(bugprone-crtp-constructor-accessibility)
81template <typename Type>
83{
84public:
85 friend std::ostream& operator<<(std::ostream& os, const Type& obj)
86 {
87 static_assert(std::is_base_of<IPrintable, Type>::value, "T must derive from IPrintable<T>");
88
89 os << outputBegin;
90 CommaSeperatedStream stream(os);
91
92 auto printable = static_cast<const IPrintable<Type>*>(&obj);
93 printable->Print(stream);
94
95 os << outputEnd;
96 return os;
97 }
98
99 virtual ~IPrintable() = default;
100
101
102protected:
103 virtual void Print(CommaSeperatedStream& stream) const = 0;
104
105
106private:
107 constexpr static const char* outputBegin = "{ ";
108 constexpr static const char* outputEnd = " }";
109};
110
111template <typename BaseType>
112class IterablePrinter : public IPrintable<BaseType>
113{
114protected:
115 void Print(CommaSeperatedStream& stream) const override
116 {
117 PrintInternal(stream);
118 }
119
120private:
121 template <typename...>
122 using void_t = void; // std::void_t not usable before c++17
123
124 template <typename Type, typename = void>
125 struct has_begin : std::false_type
126 {};
127
128 template <typename Type>
129 struct has_begin<Type, void_t<decltype(std::declval<Type>().begin())>> : std::true_type
130 {};
131
132 template <typename Type, typename = void>
133 struct has_cbegin : std::false_type
134 {};
135
136 template <typename Type>
137 struct has_cbegin<Type, void_t<decltype(std::declval<Type>().cbegin())>> : std::true_type
138 {};
139
140 template <typename Type = BaseType>
141 std::enable_if_t<has_begin<Type>::value && !has_cbegin<Type>::value, void> PrintInternal(CommaSeperatedStream& stream) const
142 {
143 std::for_each(static_cast<const BaseType*>(this)->begin(), static_cast<const BaseType*>(this)->end(), [&](auto elem) {
144 stream << elem;
145 });
146 }
147
148 template <typename Type = BaseType>
149 std::enable_if_t<has_cbegin<Type>::value, void> PrintInternal(CommaSeperatedStream& stream) const
150 {
151 std::for_each(static_cast<const BaseType*>(this)->cbegin(), static_cast<const BaseType*>(this)->cend(), [&](auto elem) {
152 stream << elem;
153 });
154 }
155};
156
157// NOLINTEND(bugprone-crtp-constructor-accessibility)
158
159} // namespace detail
160} /* namespace icv */
161} /* namespace peak */
CommaSeperatedStream & operator<<(const std::vector< Type > &vector)
CommaSeperatedStream & operator<<(const Type &value)
CommaSeperatedStream & operator<<(std::ostream &(*manip)(std::ostream &))
friend std::ostream & operator<<(std::ostream &os, const Type &obj)
virtual ~IPrintable()=default