Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ If you want to print a user-defined type, you can enable the library to print it
[See Full Example Code](./readme/user-defined-class2.cpp)

```cpp
CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(i, str());
CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(i, str());
```

![user-defined-class2.png](./readme/user-defined-class2.png)
Expand Down Expand Up @@ -322,7 +322,7 @@ The style of indents of the Container, Set and Map categories (See [Supported ty
* Member functions to be displayed must be const.
* Compile errors in this macro, such as ambiguous function calls, are never reported due to SFINAE.
*/
#define CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(members...)
#define CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(members...)

/**
* Make export_var() support enum T.
Expand Down Expand Up @@ -553,21 +553,19 @@ cpp_dump(my_enum_A);

![user-defined-enum.png](./readme/user-defined-enum.png)

#### 2. Use CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT() macro
#### 2. Use CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC() macro

This macro enables `cpp_dump()` to print any type with specified members.
This macro doesn't require the user type to be accessible from the top level (or even the type name).

However, if you do not use this macro carefully, it might cause ambiguous function call errors.
Moreover, the errors are never reported due to SFINAE, and the user type will remain unsupported.

If you use this macro only once, it won't cause ambiguous function call errors.
If you use this macro two or more times, you need to be careful of ambiguous function call errors.
If such an error occurs, it won't be reported due to SFINAE.
[See Full Example Code](./readme/user-defined-class2.cpp)

```cpp
// At top level
// CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(members...)
CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(i, str());
// CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(members...)
CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(i, str());

// Anywhere
struct class_A {
Expand Down Expand Up @@ -930,7 +928,7 @@ namespace cp = cpp_dump;
#define CPP_DUMP_SET_OPTION(...)
#define CPP_DUMP_DEFINE_EXPORT_OBJECT(...)
#define CPP_DUMP_DEFINE_EXPORT_ENUM(...)
#define CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(...)
#define CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(...)
#endif

#include <bits/stdc++.h>
Expand Down Expand Up @@ -987,7 +985,7 @@ cpp_dump() prints variables recursively, so they can dump nested variables of an
| User-defined | `CPP_DUMP_DEFINE_EXPORT_OBJECT(T, members...);` is at top level and the member functions to be displayed is const. | |
| Enum | `CPP_DUMP_DEFINE_EXPORT_ENUM(T, members...);` is at top level. | |
| Ostream | All of the above are not satisfied, `std::is_function_v<T> == false && std::is_member_pointer_v<T> == false`, and the function `std::ostream& operator<<(std::ostream&, const T &)` is defined. **The string representation of T must not be an empty string** (This makes manipulators unsupported). | |
| User-defined2 | All of the above are not satisfied, T has all members specified by just one `CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(members...);` at top level, and the member functions to be displayed is const. | |
| User-defined2 | All of the above are not satisfied, T has all members specified by just one `CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(members...);` at top level, and the member functions to be displayed is const. | |
| Asterisk | All of the above are not satisfied, `cpp_dump::enable_asterisk == true` and the function `TypeExceptT operator*(const T &)` or the const member function `TypeExceptT T::operator*() const` is defined. | Iterators |

### Display example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,44 @@
#include "../type_check.hpp"
#include "./export_object_common.hpp"

#define _p_CPP_DUMP_EXPAND_FOR_DANGEROUS_EXPORT_OBJECT(member) value.member
#define _p_CPP_DUMP_EXPAND_FOR_DANGEROUS_EXPORT_OBJECT2(member) append_output(#member, value.member)
#define _p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT_GENERIC(member) value.member
#define _p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT_GENERIC2(member) append_output(#member, value.member)

/**
* Make export_var() support every type that has the specified members.
* Member functions to be displayed must be const.
* Compile errors in this macro, such as ambiguous function calls, are never reported due to SFINAE.
*/
#define CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(...) \
namespace cpp_dump { \
\
namespace _detail { \
\
template <typename T> \
inline auto dangerous_export_object( \
const T &value, \
const std::string &indent, \
std::size_t last_line_length, \
std::size_t current_depth, \
bool fail_on_newline, \
const export_command &command \
) -> decltype(_p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_DANGEROUS_EXPORT_OBJECT, __VA_ARGS__), std::string()) { \
std::string class_name = es::class_name(get_typename<T>()); \
\
_p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; \
\
_p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_DANGEROUS_EXPORT_OBJECT2, __VA_ARGS__); \
\
_p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; \
} \
\
} /* namespace _detail */ \
\
#define CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(...) \
namespace cpp_dump { \
\
namespace _detail { \
\
template <typename T> \
inline auto export_object_generic( \
const T &value, \
const std::string &indent, \
std::size_t last_line_length, \
std::size_t current_depth, \
bool fail_on_newline, \
const export_command &command \
) -> decltype(_p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT_GENERIC, __VA_ARGS__), std::string()) { \
std::string class_name = es::class_name(get_typename<T>()); \
\
_p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; \
\
_p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT_GENERIC2, __VA_ARGS__); \
\
_p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; \
} \
\
} /* namespace _detail */ \
\
} // namespace cpp_dump

/**
* This is deprecated.
* Use CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC() instead.
*/
#define CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(...) \
CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(__VA_ARGS__)
6 changes: 3 additions & 3 deletions hpp/export_var/export_var.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@

#include "../export_command/export_command.hpp"
#include "../type_check.hpp"
#include "./dangerous_export_object.hpp"
#include "./export_arithmetic.hpp"
#include "./export_asterisk.hpp"
#include "./export_container.hpp"
#include "./export_enum.hpp"
#include "./export_exception.hpp"
#include "./export_map.hpp"
#include "./export_object.hpp"
#include "./export_object_generic.hpp"
#include "./export_ostream.hpp"
#include "./export_other/export_other.hpp"
#include "./export_pointer.hpp"
Expand Down Expand Up @@ -79,8 +79,8 @@ std::string export_var(
return export_other(value, indent, last_line_length, current_depth, fail_on_newline, command);
} else if constexpr (is_ostream<T>) {
return export_ostream(value, indent, last_line_length, current_depth, fail_on_newline, command);
} else if constexpr (is_dangerously_exportable_object<T>) {
return dangerous_export_object(
} else if constexpr (is_exportable_object_generic<T>) {
return export_object_generic(
value, indent, last_line_length, current_depth, fail_on_newline, command
);
} else {
Expand Down
18 changes: 9 additions & 9 deletions hpp/type_check.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,19 +249,19 @@ inline constexpr bool is_ostream = decltype(_is_ostream<_remove_cvref<T>>(0))::v
struct export_command;

template <typename T>
auto _is_dangerously_exportable_object(int) -> std::enable_if_t<
auto _is_exportable_object_generic(int) -> std::enable_if_t<
!_is_exportable_partial<T> && !is_ostream<T>,
decltype(dangerous_export_object(std::declval<T>(), "", 0, 0, false, std::declval<export_command>()), std::true_type())>;
decltype(export_object_generic(std::declval<T>(), "", 0, 0, false, std::declval<export_command>()), std::true_type())>;
template <typename>
std::false_type _is_dangerously_exportable_object(long);
std::false_type _is_exportable_object_generic(long);

template <typename T>
inline constexpr bool is_dangerously_exportable_object =
decltype(_is_dangerously_exportable_object<_remove_cvref<T>>(0))::value;
inline constexpr bool is_exportable_object_generic =
decltype(_is_exportable_object_generic<_remove_cvref<T>>(0))::value;

template <typename T>
auto _is_asterisk(int) -> std::enable_if_t<
!_is_exportable_partial<T> && !is_ostream<T> && !is_dangerously_exportable_object<T>
!_is_exportable_partial<T> && !is_ostream<T> && !is_exportable_object_generic<T>
&& !std::is_same_v<_remove_cvref<decltype(*std::declval<const T>())>, T>,
std::true_type>;
template <typename>
Expand All @@ -271,8 +271,8 @@ template <typename T>
inline constexpr bool is_asterisk = decltype(_is_asterisk<_remove_cvref<T>>(0))::value;

template <typename T>
inline constexpr bool is_exportable = _is_exportable_partial<T> || is_ostream<T>
|| is_dangerously_exportable_object<T> || is_asterisk<T>;
inline constexpr bool is_exportable =
_is_exportable_partial<T> || is_ostream<T> || is_exportable_object_generic<T> || is_asterisk<T>;

template <typename T>
inline constexpr bool is_iterable_like = is_container<T> || is_map<T> || is_set<T> || is_tuple<T>;
Expand All @@ -291,7 +291,7 @@ const char* _get_typename() {
#endif
}

// Currently, used only by export_exception() and CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT()
// Currently, used only by export_exception() and CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC()
template <typename T>
std::string get_typename() {
#if defined(__GNUC__) && !defined(__clang__)
Expand Down
2 changes: 1 addition & 1 deletion readme/user-defined-class2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "../dump.hpp"

CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(i, str());
CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(i, str());

int main() {
std::clog << std::endl;
Expand Down
4 changes: 2 additions & 2 deletions test/dump_indent_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ struct self_reference_class {
};

CPP_DUMP_DEFINE_EXPORT_OBJECT(class_a, int_a, str);
CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(int_b, str);
CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(str_member, pointer, ref);
CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(int_b, str);
CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(str_member, pointer, ref);

#define PRINT(x) (x), (clog << #x ";" << endl)

Expand Down
2 changes: 1 addition & 1 deletion test/dump_variable_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using namespace std;
namespace cp = cpp_dump;

CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(member_var, member_func());
CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(member_var, member_func());

namespace ns {

Expand Down
2 changes: 1 addition & 1 deletion test/odr_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct class_b {

CPP_DUMP_DEFINE_EXPORT_ENUM(enum_a, enum_a::s, enum_a::k);
CPP_DUMP_DEFINE_EXPORT_OBJECT(class_a, int_a, a_str());
CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(int_b, b_str());
CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(int_b, b_str());
CPP_DUMP_SET_OPTION_IN_GLOBAL(max_line_width, 100);
CPP_DUMP_SET_OPTION_IN_GLOBAL(max_depth, 5);
CPP_DUMP_SET_OPTION_IN_GLOBAL(max_iteration_count, 20);
Expand Down
Loading