Variant with visitor

#include <boost/variant.hpp>
#include <vector>
 
using std::vector;
typedef int Id, BallastType;
typedef double Volume, Weight, Distrib;
 
struct Container
{
  Volume volume_allowance;
  Weight weight_allowance;
  bool is_air_conditioned;
  Id id;
  // more ...
};
 
struct MultiContainer
{
  vector<Container> containers;
  Id id;
  // more ...
};
 
struct Ballast
{
  BallastType type;
  Weight weight;
  // more ...
};

using Block = 
  boost::variant<Ballast, Container, MultiContainer>;

struct Bundle
{
  Weight weight;
  Volume volume;
  Id id;
  bool requires_air_conditioning;
  // more ...
};

struct MultiBundle
{
  vector<Bundle> bundles;
  Id bundle_id;
  // more ...
};

using LoadPiece = boost::variant<Bundle, MultiBundle>;

struct Weight_allowance : boost::static_visitor<Weight>
{
  Weight operator()(const Container& cont) const
  {
    return cont.weight_allowance;
  }
     
  Weight operator()(const MultiContainer& div_cont) const
  {
    Weight wgt (0);
    for (const Container& cont : div_cont.containers)
      wgt += cont.weight_allowance;
    return wgt;
  }
     
  Weight operator()(const Ballast&) const
  {
    return Weight(0);
  }
};
 
struct Fits : boost::static_visitor<bool>
{
  bool operator()(const Container& c, const Bundle& b) const
  {
    return c.weight_allowance >= b.weight
        && c.volume_allowance >= b.volume;
  }
    
  bool operator()(const Container&   c,
                  const MultiBundle& mb) const
  {
    return bool("sum of bundles fits into c");
  }
    
  bool operator()(const MultiContainer& mc,
                  const Bundle&         b) const
  {
    for (const Container& c : mc.containers)
      if (Fits{}(c, b))
        return true;
    return false;
  }
    
  bool operator()(const MultiContainer& mc,
                  const MultiBundle&    mb) const
  {
    return bool("all bundles fit across all sub containers");
  }
     
  template <typename T>
  bool operator()(const Ballast&, const T&) const
  {
    return false;
  }
};
 
int main()
{
  Block b = Container();
  LoadPiece l = Bundle();
  Weight wgt = boost::apply_visitor(Weight_allowance(), b);
  bool  fits = boost::apply_visitor(Fits(), b, l);
}
Advertisements