Feb 042016
 

I just read Jens Wellers article regarding raw loops vs. STL algorithms.

At the end he states “When I work with Qt, there are some cases, when you only get the count and a method to access item n, like in a QListWidget:” with the example:

for(int i = 0,s=ui->lst_feeds->count();i < s; ++i)
{
    auto* item = ui->lst_feeds->item(i);
    auto si = item->data(Qt::UserRole).value< FeedItem::SharedItem >();
    if(si && si->contains(list))
        item->setCheckState(Qt::Checked);
}

And that is the point where I want bring in the possibility to use Qt widget container like objects in range based for loops or in STL algorithms. The only thing that one needs for this, is a small proxy that provides the begin(), end() interface:

template <class T, class R, int (T::*Count)() const, R *(T::*Access)(int)const>
class QtContainerProxy
{
  T *_object;

public:
  
  using value_type = R*;

  explicit QtContainerProxy(T& object)
    : _object(&object)
  {}

  QtContainerProxy(const QtContainerProxy&) = default;
  QtContainerProxy& operator=(const QtContainerProxy&) = default;

  class iterator 
  {
  public:
    using iterator_category = std::bidirectional_iterator_tag;
    using value_type = typename QtContainerProxy::value_type;
    using difference_type = ptrdiff_t;
    using pointer = value_type;
    using const_pointer = const pointer;
    using reference = value_type;
    using const_reference = const reference;

    iterator(const iterator&) = default;
    iterator& operator=(const iterator&) = default;

    iterator(QtContainerProxy& proxy, int index) 
      : _index{ index }
      , _proxy{ proxy } 
    {}

    reference operator*() const { return (_proxy._object->*Access)(_index); }

    pointer operator->() const { return operator*(); }

    iterator &operator++() {
      _index += 1;
      return *this;
    }

    iterator operator++(int) {
      iterator tmp = *this;
      ++*this;
      return tmp;
    }

    iterator &operator--() {
      _index -= 1;
      return *this;
    }

    iterator operator--(int) {
      iterator tmp = *this;
      --*this;
      return tmp;
    }

    friend bool operator==(const iterator &x, const iterator &y) {
      return &x._proxy == &y._proxy && x._index == y._index;
    }

    friend bool operator!=(const iterator &x, const iterator &y) {
      return !(x == y);
    }

  private:
    int _index;
    QtContainerProxy& _proxy;
  };

  using const_iterator = const iterator;

  iterator begin() const { return iterator(const_cast<QtContainerProxy&>(*this), 0); }
  iterator end() const { return iterator(const_cast<QtContainerProxy&>(*this), (_object->*Count)()); }
  const_iterator cbegin() const { return begin(); }
  const_iterator cend() const { return end(); }
};


So how to use it in the example from above?

For better readability and perhaps later reuse at other places let’s define this type:

using ListWidgetProxy = QtContainerProxy<QListWidget, QListWidgetItem, &QListWidget::count, &QListWidget::item>;

And now the example becomes:

for(auto& item : ListWidgetProxy(*ui->lst_feeds)) {
  auto si = item->data(Qt::UserRole).value< FeedItem::SharedItem >();
  if(si && si->contains(list))
      item->setCheckState(Qt::Checked);
}

The template might be simplified in regard of the interface. But Visual Studio 2013, the compiler I have to use currently, lags certain C++11 features.

What do you think? So feedback is welcome.

 

 

First draft of C++ library contract_light published

 Uncategorized  Comments Off on First draft of C++ library contract_light published
Oct 212014
 

I am happy to announce that I published a C++ library that offers a lightweight version of a Design by Contract functionality. You can find it under http://github.com/FelixPetriconi/contract_light.

Here is a simple example for the beginning. More to come later

class Rect 
{
  // Use this define if an invariant is defined. If no invariant is defined
  // no need to do it
  CONTRACTOR
  int w_;
  int h_;
public:
  Rect() : w_(0), h_(0) {}
  
  ~Rect() {
    // checking that the invariants are fulfilled, even before destruction
    INVARIANT;
  }
  
  void setWidth(int newW) {
    // setting the pre condition of this method; the invariant is checked 
    // once at the end of the scope
    PRECONDITION [&] { return newW >= 0; };
    // setting the post condition; the invariant is checked only once after 
    // leaving the scope, regardless of the number of pre- and/or post-conditions
    POSTCONDITION [&, this] { return newW == w_; };
    w_ = newW;
    
    // There is no need to define here INVARIANT here. This is done automatically
    // whenever there is a bool invariant() const method is defined
  }
  
  int size() const {
    int result;
    POSTCONDITION [&] { return result == w_ * h_; }
    result = w_ * h_;
    
    return result;
  }
  
  bool invariant() const {
    return w_ >= 0 && h_ >= 0;
  }
};