Framework — adl

#include <type_traits>
#include <vector>
#include <utility>
#include <memory>
#include <boost/optional.hpp>

namespace framework
{
  template <typename T>
    typename std::enable_if<std::is_trivial<T>::value,
                            size_t>::type
    mem_usage1(const T& v) { return sizeof v; }
}

namespace framework
{
  template <typename T, typename U>
    size_t mem_usage1(const std::pair<T, U>& v);
  
  template <typename T>
    size_t mem_usage1(const std::vector<T>& v)
    { 
      size_t ans = sizeof(v);
      for (const T& e : v) ans += mem_usage1(e);
      ans += (v.capacity() - v.size()) * sizeof(T);
      return ans;
    }
  
  template <typename T, typename U>
    size_t mem_usage1(const std::pair<T, U>& v)
    { 
      return mem_usage1(v.first) + mem_usage1(v.second);
    }

  template <typename T>
    size_t mem_usage(const T& v) { return mem_usage1(v); }
}

namespace framework
{
  namespace algo
  {
    template <typename T>
    size_t score(const T& v)
    {
      // do some more things
      return mem_usage(v);
    }
  }
}

namespace framework
{
  template <typename T>
  class Array
  {
    std::unique_ptr<T[]> ptr_;
    size_t size_;
    
  public:
    explicit Array(size_t s) : ptr_(new T [s]), size_(s) {}
    T const* begin() const { return &ptr_[0]; }
    T const* end() const { return &ptr_[size_]; }
  };
  
  template <typename T>
    size_t mem_usage1(const Array<T>& v)
    {
      size_t ans = sizeof(v);
      for (const T& e : v) ans += mem_usage1(e);
      return ans;
    }
}

namespace boost
{
  template <typename T>
    size_t mem_usage1(const optional<T>& v)
    {
      using framework::mem_usage1;
      
      size_t ans = sizeof(v);
      if (v) ans += mem_usage1(*v) - sizeof(*v);
      return ans;
    }
}

int main()
{  
  int i = 0;
  framework::Array<int> a (10);
  std::vector<int> v (10);
  std::vector<std::pair<int, int>> vp;
  boost::optional<int> o;
  boost::optional<std::vector<int>> ov;
  
  framework::algo::score(i);
  framework::algo::score(a);
  framework::algo::score(v);
  framework::algo::score(o);
  framework::algo::score(vp);
  framework::algo::score(ov);

  framework::mem_usage(i);
  framework::mem_usage(a);
  framework::mem_usage(v);
  framework::mem_usage(o);
  framework::mem_usage(vp);
  framework::mem_usage(ov);
}