diff --git a/lib/Basics/debugging.cpp b/lib/Basics/debugging.cpp index fbef571206..c559c7c490 100644 --- a/lib/Basics/debugging.cpp +++ b/lib/Basics/debugging.cpp @@ -279,3 +279,8 @@ void TRI_FlushDebugging(char const* file, int line, char const* message) { Logger::flush(); Logger::shutdown(); } + +template<> char const conpar::open = '{'; +template<> char const conpar::close = '}'; +template<> char const conpar::open = '['; +template<> char const conpar::close = ']'; diff --git a/lib/Basics/debugging.h b/lib/Basics/debugging.h index 45cd584994..f0c311c3a5 100644 --- a/lib/Basics/debugging.h +++ b/lib/Basics/debugging.h @@ -19,6 +19,7 @@ /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Jan Steemann +/// @author Kaveh Vahedipour //////////////////////////////////////////////////////////////////////////////// #ifndef ARANGODB_BASICS_DEBUGGING_H @@ -99,6 +100,67 @@ void TRI_LogBacktrace(); void TRI_FlushDebugging(); void TRI_FlushDebugging(char const* file, int line, char const* message); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief container traits +//////////////////////////////////////////////////////////////////////////////// + +namespace container_traits { + +using tc = char[2]; + +template struct is_container { + static tc& test(...); + + template + static char test(U&&, decltype(std::begin(std::declval()))* = 0); + static constexpr bool value = sizeof(test(std::declval())) == 1; +}; + +template < typename T > struct is_associative { + static tc& test(...) ; + + template < typename U > + static char test(U&&, typename U::key_type* = 0) ; + static constexpr bool value = sizeof( test( std::declval() ) ) == 1 ; +}; + +} + +template < typename T > struct is_container : + std::conditional<(container_traits::is_container::value || std::is_array::value) + && !std::is_same::type>::value + && !std::is_same::type>::value + && !std::is_same::type>::value + && !std::is_same::type>::value + && !std::is_same::value + && !std::is_same::value, std::true_type, std::false_type >::type {}; + +template < typename T > struct is_associative : + std::conditional< container_traits::is_container::value && container_traits::is_associative::value, + std::true_type, std::false_type >::type {}; + + + +//////////////////////////////////////////////////////////////////////////////// +/// @brief no std::enable_if_t in c++11 +//////////////////////////////////////////////////////////////////////////////// + +#if __cplusplus <= 201103L +namespace std { +template< bool B, class T = void > +using enable_if_t = typename std::enable_if::type; +} +#endif + +//////////////////////////////////////////////////////////////////////////////// +/// @brief forward declaration for pair output below +//////////////////////////////////////////////////////////////////////////////// + +template +std::enable_if_t::value, std::ostream&> +operator<< (std::ostream& o, T const& t); + //////////////////////////////////////////////////////////////////////////////// /// @brief dump pair contents to an ostream //////////////////////////////////////////////////////////////////////////////// @@ -113,115 +175,31 @@ std::ostream& operator<<(std::ostream& stream, std::pair const& obj) { /// @brief dump vector contents to an ostream //////////////////////////////////////////////////////////////////////////////// -template -std::ostream& operator<<(std::ostream& stream, std::vector const& data) { - bool first = true; +template +struct conpar { + static char const open; + static char const close; +}; - stream << "["; - for (auto const& it : data) { +template< bool B, class T = void > +using enable_if_t = typename std::enable_if::type; + +template +enable_if_t::value, std::ostream&> +operator<< (std::ostream& o, T const& t) { + o << conpar::value>::open; + bool first = true; + for (auto const& i : t) { if (first) { - stream << " "; + o << " "; first = false; } else { - stream << ", "; + o << ", "; } - stream << it; + o << i ; } - stream << " ]"; - - return stream; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief dump deque contents to an ostream -//////////////////////////////////////////////////////////////////////////////// - -template -std::ostream& operator<<(std::ostream& stream, std::deque const& data) { - bool first = true; - - stream << "["; - for (auto const& it : data) { - if (first) { - stream << " "; - first = false; - } else { - stream << ", "; - } - stream << it; - } - stream << " ]"; - - return stream; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief dump unordered_set contents to an ostream -//////////////////////////////////////////////////////////////////////////////// - -template -std::ostream& operator<<(std::ostream& stream, std::unordered_set const& data) { - bool first = true; - - stream << "{"; - for (auto const& it : data) { - if (first) { - stream << " "; - first = false; - } else { - stream << ", "; - } - stream << it; - } - stream << " }"; - - return stream; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief dump unordered_map contents to an ostream -//////////////////////////////////////////////////////////////////////////////// - -template -std::ostream& operator<<(std::ostream& stream, std::unordered_map const& data) { - bool first = true; - - stream << "{"; - for (auto const& it : data) { - if (first) { - stream << " "; - first = false; - } else { - stream << ", "; - } - stream << it.first << ": " << it.second; - } - stream << " }"; - - return stream; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief dump map contents to an ostream -//////////////////////////////////////////////////////////////////////////////// - -template -std::ostream& operator<<(std::ostream& stream, std::map const& data) { - bool first = true; - - stream << "{"; - for (auto const& it : data) { - if (first) { - stream << " "; - first = false; - } else { - stream << ", "; - } - stream << it.first << ": " << it.second; - } - stream << " }"; - - return stream; + o << " " << conpar::value>::close; + return o; } #endif