Framework — adl+tag

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


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

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_usage2(const Array<T>& v, adl_tag)
    {
      size_t ans = sizeof(v);
      for (const T& e : v)
        ans += mem_usage2(e, adl_tag{});
      return ans;
    }
}

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

namespace framework
{
  template <typename T>
    size_t mem_usage2(const boost::optional<T>& v, adl_tag t)
    {
      size_t ans = sizeof(v);
      if (v) ans += mem_usage2(*v, t) - 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);
}