sharkdp / dbg-macro

A dbg(…) macro for C++

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Broken output of containers

YarikTH opened this issue · comments

See example below.
https://godbolt.org/z/vnxaqq

#include <dbg.h>

int main()
{
    std::vector<std::pair<std::string, int>> container = {
        {"30+2", 32}, {"30-2", 28}, {"30*2", 60}
    };
    dbg(container);
}

Here we have a vector of pairs of strings. Despite the library has pretty_print overloads for std::pair, std::string, and container they don't fully work with each other. It seems that the reason is the fact, that pretty_print overloads for std::pair and std::string are defined just after container overload and thus they aren't visible from pretty_print overload for containers.

A possible solution is adding declarations for all the pretty_print overloads before their definitions. For e.g. in my example, adding declarations for pair and string overloads before container overload fixes the problem.

inline bool pretty_print(std::ostream& stream, const std::string& value);

template <typename T1, typename T2>
inline bool pretty_print(std::ostream& stream, const std::pair<T1, T2>& value);



template <typename Container>
inline typename std::enable_if<detail::is_container<const Container&>::value,
                               bool>::type
pretty_print(std::ostream& stream, const Container& value) {

Thank you for reporting this. That should be fixed.

If there is a solution without duplicating all declarations, that would be great. But I guess that's actually the right thing to do.

I think that alternative is using one big function pretty_print with constexpr_if branches. I used it in another project. Easy to maintain, easy to understand. But need to bump std to c++17. I think that for this project it's unwanted.

    template<typename Field>
    inline void process_field( const size_t depth, std::ostream& ss, const char* field_name, Field&& field )
    {
        if constexpr( is_element_container_v<Field> || is_key_value_container_v<Field> || is_pair_v<Field> || is_tuple_v<Field> )
        {
            if constexpr( is_element_container_v<Field> )
            {
                constexpr bool is_simple_element = is_simple_type_v<typename remove_cvref_t<Field>::value_type>;
                ...
            }
            else if constexpr( is_key_value_container_v<Field> )
            {
                ...
            }
            else if constexpr( is_pair_v<Field> )
            {
                ...
            }
            else if constexpr( is_tuple_v<Field> )
            {
                process_tuple_fields( depth + 1, ss, field );
            }
            else
            {
                static_assert( !std::is_same_v<Field,Field>, "We shouldn't be here! Something went wrong." );
            }
        }
        else if constexpr( has_dereference_operator_v<remove_cvref_t<Field>> )
        {
            if( !field )
            {
                apply_depth();
                append_field_name();
                ss << "nullptr";
            }
            else
            {
                process_field( depth, ss, field_name, *field );
            }
        }
        else if constexpr( has_ostream_operator_v<Field> )
        {
            ...
        }
        else if constexpr( std::is_enum_v<remove_cvref_t<Field>> )
        {
            ...
        }
        else
        {
            static_assert( !std::is_same_v<Field,Field>, "Given type is not supported. Please overload std::ostream operator or something." );
        }
    }

Yes. I would like to maintain C++11 backwards compatibility.

Hi, are you planning to fix that issue?
I guess it's kinda important to be able to print nested containers.
I can also add that it doesn't work well with tuples of containers:

  tuple<vector<int>>hm{{1}};
  dbg(hm);

outputs a lot of errors.
If not, IMHO it would be great to add a message which says this type is not supported or something. Currently it breaks the compilation.

Hi, are you planning to fix that issue?

Yes, this should be fixed. We can go the easy way for now and duplicate all declarations. Any help would be very much appreciated.

Fixed by @YarikTH in #110