Adobe.Poly — Holder

#include <cassert>
#include <adobe/poly.hpp>
#include <boost/concept_check.hpp>

template <typename H>
struct HolderConcept : boost::Assignable<H>
                     , boost::CopyConstructible<H>
{
  BOOST_CONCEPT_USAGE(HolderConcept)
  {
    h.store(i);
    i = load(h);
  }
  
private:
    H h;
  int i;
};

struct SomeHolder
{
  int val = 0;
  void store(int i) { val = i; }
};
int load(SomeHolder & h) { return h.val; }

BOOST_CONCEPT_ASSERT((HolderConcept<SomeHolder>));

// Type erased interface

struct HolderIface : adobe::poly_copyable_interface
{
  virtual void store(int) = 0;
  virtual int free_load() = 0;
};

template <typename T>
struct HolderImpl 
  : adobe::optimized_storage_type<T, HolderIface>::type
{
  using base_t = typename 
    adobe::optimized_storage_type<T, HolderIface>::type;

  BOOST_CONCEPT_ASSERT((HolderConcept<T>));
  HolderImpl(T x) : base_t(x) {}
  HolderImpl(adobe::move_from<HolderImpl> x) 
    : base_t(adobe::move_from<base_t>(x.source)) {}
  
  void store(int i) override { this->get().store(i); }
  int free_load() override { return load(this->get()); }
};

struct Holder : adobe::poly_base<HolderIface, HolderImpl>
{
  using base_t =  adobe::poly_base<HolderIface, HolderImpl> ;
  using base_t::base_t;

  Holder(adobe::move_from<Holder> x) 
    : base_t(adobe::move_from<base_t>(x.source)) {}
  
  void store(int i) 
  { interface_ref().store(i); }

  friend int load(Holder & h) 
  { return h.interface_ref().free_load(); }
};

typedef adobe::poly<Holder> AnyHolder;
BOOST_CONCEPT_ASSERT((HolderConcept<AnyHolder>));

int main()
{
  AnyHolder h {SomeHolder{}};
  h.store(2);
  int i = load(h);
  assert (i == 2);
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s