Skip to content

Commit

Permalink
Utility: move STL-specific stuff to DebugStl.h.
Browse files Browse the repository at this point in the history
There's still <iosfwd> and <utility> lurking around, but even with that
the amount of preprocessed lines goes down from 14k to 3k under C++11
and from 17k to 4k under C++17. Nice.

I had to use the IsStringLike type trait to avoid forward-declaring /
including std::string and due to that there's a new operator<< for
std::basic_string of types other than char, since those would be now
interpreted as string-like. For now I'm keeping the current behavior of
printing only std::string as a string and all other (e.g.
std::u32string) as containers, but maybe it might make sense to revisit
this in the future and print all those types as strings.
  • Loading branch information
mosra committed Apr 3, 2019
1 parent 70b7dd0 commit 89da382
Show file tree
Hide file tree
Showing 24 changed files with 197 additions and 87 deletions.
8 changes: 8 additions & 0 deletions doc/corrade-changelog.dox
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ namespace Corrade {
from looking like it works on directories only, but such name then caused
people to ask if it works on directories as well, not helping anything.

@subsection corrade-changelog-latest-compatibility Potential compatibility breakages, removed APIs

- Support for @ref std::tuple and @ref std::string in
@ref Utility::Debug is now provided through a separate header,
@ref Corrade/Utility/DebugStl.h, to speed up compile times. Since including
it for backwards compatibility would practically revert the optimization,
you have to @cpp #include @ce it explicitly where needed.

@subsection corrade-changelog-latest-documentation Documentation

- Updated docs of the @ref Corrade/Utility/Macros.h header mentioning what
Expand Down
2 changes: 2 additions & 0 deletions src/Corrade/Containers/EnumSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
* @brief Function @ref Corrade::Containers::enumSetDebugOutput()
*/

#include <initializer_list>

#include "Corrade/Containers/EnumSet.h"
#include "Corrade/Utility/Debug.h"

Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/PluginManager/AbstractManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "Corrade/PluginManager/AbstractPlugin.h"
#include "Corrade/PluginManager/PluginMetadata.h"
#include "Corrade/Utility/Assert.h"
#include "Corrade/Utility/Debug.h"
#include "Corrade/Utility/DebugStl.h"
#include "Corrade/Utility/Configuration.h"
#include "Corrade/Utility/String.h"

Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/TestSuite/Compare/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <algorithm> /* std::max() */
#endif

#include "Corrade/Utility/Debug.h"
#include "Corrade/Utility/DebugStl.h"
#include "Corrade/Utility/Directory.h"

namespace Corrade { namespace TestSuite {
Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/TestSuite/Compare/FileToString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#include <algorithm> /* std::max() */
#endif

#include "Corrade/Utility/Debug.h"
#include "Corrade/Utility/DebugStl.h"
#include "Corrade/Utility/Directory.h"

namespace Corrade { namespace TestSuite {
Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/TestSuite/Compare/StringToFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#include <algorithm> /* std::max() */
#endif

#include "Corrade/Utility/Debug.h"
#include "Corrade/Utility/DebugStl.h"
#include "Corrade/Utility/Directory.h"

namespace Corrade { namespace TestSuite {
Expand Down
1 change: 1 addition & 0 deletions src/Corrade/TestSuite/Tester.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "Corrade/TestSuite/Compare/FloatingPoint.h"
#include "Corrade/TestSuite/visibility.h"
#include "Corrade/Utility/Debug.h"
#include "Corrade/Utility/DebugStl.h" /** @todo remove once not needed */
#include "Corrade/Utility/Macros.h"

#ifdef CORRADE_TARGET_EMSCRIPTEN
Expand Down
1 change: 1 addition & 0 deletions src/Corrade/Utility/AbstractHash.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <string>

#include "Corrade/Utility/Debug.h"
#include "Corrade/Utility/DebugStl.h"

namespace Corrade { namespace Utility {

Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/Utility/Arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#include <sstream>

#include "Corrade/Utility/Assert.h"
#include "Corrade/Utility/Debug.h"
#include "Corrade/Utility/DebugStl.h"
#include "Corrade/Utility/String.h"

/* For Arguments::environment() */
Expand Down
1 change: 1 addition & 0 deletions src/Corrade/Utility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ if(WITH_UTILITY)
ConfigurationGroup.h
ConfigurationValue.h
Debug.h
DebugStl.h
Directory.h
Endianness.h
Format.h
Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/Utility/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

#include "Corrade/Containers/Array.h"
#include "Corrade/Utility/Assert.h"
#include "Corrade/Utility/Debug.h"
#include "Corrade/Utility/DebugStl.h"
#include "Corrade/Utility/Directory.h"
#include "Corrade/Utility/String.h"

Expand Down
19 changes: 13 additions & 6 deletions src/Corrade/Utility/Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
#endif
#endif

#include "Corrade/Utility/DebugStl.h"

namespace Corrade { namespace Utility {

namespace {
Expand Down Expand Up @@ -326,8 +328,6 @@ template<class T> Debug& Debug::print(const T& value) {
return *this;
}

Debug& Debug::operator<<(const std::string& value) { return print(value); }

Debug& Debug::operator<<(const void* const value) {
std::ostringstream o;
o << "0x" << std::hex << reinterpret_cast<std::uintptr_t>(value);
Expand Down Expand Up @@ -385,10 +385,6 @@ Debug& Debug::operator<<(std::nullptr_t) {
}

#ifndef DOXYGEN_GENERATING_OUTPUT
Debug& Debug::operator<<(Implementation::DebugOstreamFallback&& value) {
return print(value);
}

/* Doxygen can't match this to the declaration, eh. */
Debug& operator<<(Debug& debug, Debug::Color value) {
switch(value) {
Expand All @@ -411,6 +407,17 @@ Debug& operator<<(Debug& debug, Debug::Color value) {

return debug << "Debug::Color(" << Debug::nospace << reinterpret_cast<void*>(static_cast<unsigned char>(char(value))) << Debug::nospace << ")";
}

/* For some reason Doxygen can't match this with the declaration in DebugStl.h */
Debug& operator<<(Debug& debug, const std::string& value) {
return debug.print(value);
}
#endif

#ifndef DOXYGEN_GENERATING_OUTPUT
Debug& operator<<(Debug& debug, Implementation::DebugOstreamFallback&& value) {
return debug.print(value);
}
#endif

}}
107 changes: 35 additions & 72 deletions src/Corrade/Utility/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@

/** @file
* @brief Class @ref Corrade::Utility::Debug, @ref Corrade::Utility::Warning, @ref Corrade::Utility::Error, @ref Corrade::Utility::Fatal
* @see @ref Corrade/Utility/DebugStl.h
*/

#include <iosfwd>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility> /** @todo consider putting this away as well (900 LOC) */

#include "Corrade/Utility/Macros.h"
#include "Corrade/Containers/EnumSet.h"
Expand All @@ -42,8 +42,6 @@

namespace Corrade { namespace Utility {

namespace Implementation { struct DebugOstreamFallback; }

/**
@brief Debug output handler
Expand All @@ -53,11 +51,20 @@ with newline character. Example usage:
@snippet Utility.cpp Debug-usage
Support for printing more types can be added by implementing function
@ref operator<<(Debug&, const T&) for given type. If there is no
@cpp operator<<() @ce implemented for printing given type using the @ref Debug
class, suitable @ref std::ostream @cpp operator<<() @ce overload is used as
fallback, if found.
Support for printing more types can be added by implementing an overload of
@ref operator<<(Debug&, const T&) for given type.
@section Utility-Debug-stl Printing STL types
To optimize compile times, the @ref Corrade/Utility/Debug.h header provides
only support for printing builtin types, generic iterable containers and
@ref std::pair. Printing of @ref std::string and @ref std::tuple is possible if
you @cpp #include @ce a separate @ref Corrade/Utility/DebugStl.h header. This
header also provides a fallback to @ref std::ostream @cpp operator<<() @ce
overloads, if there's no @cpp operator<<() @ce implemented for printing given
type using @ref Debug. Note that printing @ref std::vector or @ref std::map
containers is already possible with the generic iterable container support in
@ref Corrade/Utility/Debug.h.
@section Utility-Debug-scoped-output Scoped output redirection
Expand Down Expand Up @@ -370,9 +377,9 @@ class CORRADE_UTILITY_EXPORT Debug {
*
* If there is already something in the output, puts a space before
* the value, unless @ref nospace() was set immediately before.
* @see @ref operator<<(Debug&, const T&)
* @see @ref operator<<(Debug&, const std::string&),
* @ref operator<<(Debug&, const T&)
*/
Debug& operator<<(const std::string& value);
Debug& operator<<(const char* value); /**< @overload */
Debug& operator<<(const void* value); /**< @overload */
Debug& operator<<(bool value); /**< @overload */
Expand Down Expand Up @@ -430,9 +437,13 @@ class CORRADE_UTILITY_EXPORT Debug {
*/
Debug& operator<<(std::nullptr_t);

#ifndef DOXYGEN_GENERATING_OUTPUT
Debug& operator<<(Implementation::DebugOstreamFallback&& value);
#endif
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#endif
/* Used by the out-of-class operator<<(Debug&, const std::string&) and
operator<<(Debug&, Implementation::DebugOstreamFallback&&) which is
defined in DebugStl.h. */
template<class T> CORRADE_UTILITY_LOCAL Debug& print(const T& value);

#ifndef DOXYGEN_GENERATING_OUTPUT
protected:
Expand Down Expand Up @@ -466,7 +477,6 @@ class CORRADE_UTILITY_EXPORT Debug {
static CORRADE_UTILITY_LOCAL bool _globalColorBold;
#endif

template<class T> CORRADE_UTILITY_LOCAL Debug& print(const T& value);
CORRADE_UTILITY_LOCAL void resetColorInternal();

std::ostream* _previousGlobalOutput;
Expand All @@ -493,23 +503,23 @@ template<class T> inline Debug& operator<<(Debug&& debug, const T& value) {
#endif

#ifdef DOXYGEN_GENERATING_OUTPUT
/** @relates Debug
@brief Operator for printing custom types to debug
/** @relatesalso Debug
@brief Operator for printing custom types to debug output
@param debug Debug class
@param value Value to be printed
Support for printing custom types (i.e. those not handled by @ref std::iostream)
can be added by implementing this function for given type.
The function should convert the type to one of supported types (such as
@ref std::string) and then call @ref Debug::operator<<(const std::string&) with
The function should convert the type to one of supported types (such as the
builtin types or @ref std::string) and then call @ref Debug::operator<<() with
it. You can also use @ref Debug::nospace() and @ref Debug::newline().
*/
template<class T> Debug& operator<<(Debug& debug, const T& value);
#endif

/** @relates Debug
@brief Operator for printing iterable types to debug
/** @relatesalso Debug
@brief Operator for printing iterable types to debug output
Prints the value as @cb{.shell-session} {a, b, c} @ce.
*/
Expand All @@ -518,7 +528,7 @@ template<class Iterable> Debug& operator<<(Debug& debug, const Iterable& value)
#else
/* libc++ from Apple's Clang "4.2" (3.2-svn) doesn't have constexpr operator
bool for std::integral_constant, thus we need to use ::value instead */
template<class Iterable> Debug& operator<<(typename std::enable_if<IsIterable<Iterable>::value && !std::is_same<Iterable, std::string>::value, Debug&>::type debug, const Iterable& value)
template<class Iterable> Debug& operator<<(typename std::enable_if<IsIterable<Iterable>::value && !IsStringLike<Iterable>::value, Debug&>::type debug, const Iterable& value)
#endif
{
debug << "{" << Debug::nospace;
Expand All @@ -544,39 +554,13 @@ namespace Implementation {
typedef Sequence<sequence...> Type;
};
#endif

/* Used by operator<<(Debug&, std::tuple<>...) */
template<class T> inline void tupleDebugOutput(Debug&, const T&, Sequence<>) {}
template<class T, std::size_t i, std::size_t ...sequence> void tupleDebugOutput(Debug& debug, const T& tuple, Sequence<i, sequence...>) {
debug << std::get<i>(tuple);
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4127) /* conditional expression is constant (of course) */
#endif
if(i + 1 != std::tuple_size<T>::value)
debug << Debug::nospace << ",";
#ifdef _MSC_VER
#pragma warning(pop)
#endif
tupleDebugOutput(debug, tuple, Sequence<sequence...>{});
}
}

/** @relates Debug
@brief Operator for printing tuple types to debug
/** @relatesalso Debug
@brief Print a @ref std::pair to debug output
Prints the value as @cb{.shell-session} (first, second, third...) @ce.
Prints the value as @cb{.shell-session} (first, second) @ce.
*/
template<class ...Args> Debug& operator<<(Debug& debug, const std::tuple<Args...>& value) {
debug << "(" << Debug::nospace;
Implementation::tupleDebugOutput(debug, value, typename Implementation::GenerateSequence<sizeof...(Args)>::Type{});
debug << Debug::nospace << ")";
return debug;
}

/** @relates Debug
* @overload
*/
template<class T, class U> Debug& operator<<(Debug& debug, const std::pair<T, U>& value) {
return debug << "(" << Debug::nospace << value.first << Debug::nospace << "," << value.second << Debug::nospace << ")";
}
Expand Down Expand Up @@ -794,27 +778,6 @@ class CORRADE_UTILITY_EXPORT Fatal: public Error {
/** @debugoperatorclassenum{Debug,Debug::Color} */
CORRADE_UTILITY_EXPORT Debug& operator<<(Debug& debug, Debug::Color value);

namespace Implementation {

/* Used by Debug::operator<<(Implementation::DebugOstreamFallback&&) */
struct DebugOstreamFallback {
template<class T> /*implicit*/ DebugOstreamFallback(const T& t): applier(&DebugOstreamFallback::applyImpl<T>), value(&t) {}

void apply(std::ostream& s) const {
(this->*applier)(s);
}

template<class T> void applyImpl(std::ostream& s) const {
s << *static_cast<const T*>(value);
}

using ApplierFunc = void(DebugOstreamFallback::*)(std::ostream&) const;
const ApplierFunc applier;
const void* value;
};

}

}}

#endif
Loading

0 comments on commit 89da382

Please sign in to comment.