Skip to content

Comments requested about modifier: qdebuggable (Qt debug) #58

@miemoe

Description

@miemoe

I tried to add a modifier, that accesses more functionality.
I program a lot with the Qt Framework and though how to make a typical line:

int foo = 0;
qDebug() << foo;

available for a strong typed int.

A simple

using myint = strong::type<int, struct my_int_>;
myint foo{0};
qDebug() << foo;

does not work, it won't compile because QDebug does not know anything about myint.

One way would be to convert it back to its base type

using myint = strong::type<int, struct my_int_>;
myint foo{0};
qDebug() << (int)foo;

but this won't work, as the conversion to int has to be added as a modifier:

using myint = strong::type<int, struct my_int_, strong::convertible_to<int>>;
myint foo{0};
qDebug() << (int)foo;

However, this does not

  • look nice and
  • if I change the underlying type to something more appropriate for the strong type, it might even not be convertable to int anymore!

I could get rid of the (int) C-style converter if I'd use the modifier: strong::implicitly_convertible_to<Ts...> but this only helps for the first problem. And it would feel like washing away the "strong" in Strong Types ...

Looking at the documentation of how QDebug in Qt works I tried to add a new modifier: qdebuggable.

I would like to kindly request comments from you, if the modifier is appropriate, to what I want to reach:

#pragma once

#include <strong_type/type.hpp>

#include <QDebug>

namespace strong
{
struct qdebuggable
   {
      template <typename T, typename = void>
      class modifier {
            static_assert(impl::always_false<T>,
            "Underlying type must be qdebuggable");
         };
   };


template <typename T, typename Tag, typename ... M>
class qdebuggable::modifier<
      ::strong::type<T, Tag, M...>,
      impl::void_t<decltype(operator<<(std::declval<QDebug>(), std::declval<const T&>()))>
>
   {
   using type = ::strong::type<T, Tag, M...>;
   public:
   friend
         auto
         operator<<(
            QDebug dbg,
            const type& value)
         noexcept(noexcept(operator<<(std::declval<QDebug>(), std::declval<const T&>())))
         -> decltype(operator<<(std::declval<QDebug>(), std::declval<const T&>()))
      {
         dbg << value_of(value);
         return dbg;
      }
   };
}

I tried it with some base types that are supported by QDebug directly and also by User Defined Types as base type where a QDebug stream operator was added to.
As the QLoggingCategory also relies on QDebug mechanism all Qt Debugging seems to work fine.

The Qt Framwork also offers some similar patterns with QDataStream and QTextStream. Probably there are more...

But befor I sit on these, I'd like to be sure that this first modifier is "right".

Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions