text: #ifndef _C4_STD_TUPLE_HPP_
  #define _C4_STD_TUPLE_HPP_
  
  /** @file tuple.hpp */
  
  #include "c4/format.hpp"
  #include <tuple>
  
  /** this is a work in progress */
  #undef C4_TUPLE_TO_CHARS
  
  namespace c4 {
  
  #ifdef C4_TUPLE_TO_CHARS
  namespace detail {
  
  template< size_t Curr, class... Types >
  struct tuple_helper
  {
      static size_t do_cat(substr buf, std::tuple< Types... > const& tp)
      {
          size_t num = to_chars(buf, std::get<Curr>(tp));
          buf = buf.len >= num ? buf.sub(num) : substr{};
          num += tuple_helper< Curr+1, Types... >::do_cat(buf, tp);
          return num;
      }
  
      static size_t do_uncat(csubstr buf, std::tuple< Types... > & tp)
      {
          size_t num = from_str_trim(buf, &std::get<Curr>(tp));
          if(num == csubstr::npos) return csubstr::npos;
          buf = buf.len >= num ? buf.sub(num) : substr{};
          num += tuple_helper< Curr+1, Types... >::do_uncat(buf, tp);
          return num;
      }
  
      template< class Sep >
      static size_t do_catsep_more(substr buf, Sep const& sep, std::tuple< Types... > const& tp)
      {
          size_t ret = to_chars(buf, sep), num = ret;
          buf  = buf.len >= ret ? buf.sub(ret) : substr{};
          ret  = to_chars(buf, std::get<Curr>(tp));
          num += ret;
          buf  = buf.len >= ret ? buf.sub(ret) : substr{};
          ret  = tuple_helper< Curr+1, Types... >::do_catsep_more(buf, sep, tp);
          num += ret;
          return num;
      }
  
      template< class Sep >
      static size_t do_uncatsep_more(csubstr buf, Sep & sep, std::tuple< Types... > & tp)
      {
          size_t ret = from_str_trim(buf, &sep), num = ret;
          if(ret == csubstr::npos) return csubstr::npos;
          buf  = buf.len >= ret ? buf.sub(ret) : substr{};
          ret  = from_str_trim(buf, &std::get<Curr>(tp));
          if(ret == csubstr::npos) return csubstr::npos;
          num += ret;
          buf  = buf.len >= ret ? buf.sub(ret) : substr{};
          ret  = tuple_helper< Curr+1, Types... >::do_uncatsep_more(buf, sep, tp);
          if(ret == csubstr::npos) return csubstr::npos;
          num += ret;
          return num;
      }
  
      static size_t do_format(substr buf, csubstr fmt, std::tuple< Types... > const& tp)
      {
          auto pos = fmt.find("{}");
          if(pos != csubstr::npos)
          {
              size_t num = to_chars(buf, fmt.sub(0, pos));
              size_t out = num;
              buf  = buf.len >= num ? buf.sub(num) : substr{};
              num  = to_chars(buf, std::get<Curr>(tp));
              out += num;
              buf  = buf.len >= num ? buf.sub(num) : substr{};
              num  = tuple_helper< Curr+1, Types... >::do_format(buf, fmt.sub(pos + 2), tp);
              out += num;
              return out;
          }
          else
          {
              return format(buf, fmt);
          }
      }
  
      static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp)
      {
          auto pos = fmt.find("{}");
          if(pos != csubstr::npos)
          {
              size_t num = pos;
              size_t out = num;
              buf  = buf.len >= num ? buf.sub(num) : substr{};
              num  = from_str_trim(buf, &std::get<Curr>(tp));
              out += num;
              buf  = buf.len >= num ? buf.sub(num) : substr{};
              num  = tuple_helper< Curr+1, Types... >::do_unformat(buf, fmt.sub(pos + 2), tp);
              out += num;
              return out;
          }
          else
          {
              return tuple_helper< sizeof...(Types), Types... >::do_unformat(buf, fmt, tp);
          }
      }
  
  };
  
  /** @todo VS compilation fails for this class */
  template< class... Types >
  struct tuple_helper< sizeof...(Types), Types... >
  {
      static size_t do_cat(substr /*buf*/, std::tuple<Types...> const& /*tp*/) { return 0; }
      static size_t do_uncat(csubstr /*buf*/, std::tuple<Types...> & /*tp*/) { return 0; }
  
      template< class Sep > static size_t do_catsep_more(substr /*buf*/, Sep const& /*sep*/, std::tuple<Types...> const& /*tp*/) { return 0; }
      template< class Sep > static size_t do_uncatsep_more(csubstr /*buf*/, Sep & /*sep*/, std::tuple<Types...> & /*tp*/) { return 0; }
  
      static size_t do_format(substr buf, csubstr fmt, std::tuple<Types...> const& /*tp*/)
      {
          return to_chars(buf, fmt);
      }
  
      static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple<Types...> const& /*tp*/)
      {
          return 0;
      }
  };
  
  } // namespace detail
  
  template< class... Types >
  inline size_t cat(substr buf, std::tuple< Types... > const& tp)
  {
      return detail::tuple_helper< 0, Types... >::do_cat(buf, tp);
  }
  
  template< class... Types >
  inline size_t uncat(csubstr buf, std::tuple< Types... > & tp)
  {
      return detail::tuple_helper< 0, Types... >::do_uncat(buf, tp);
  }
  
  template< class Sep, class... Types >
  inline size_t catsep(substr buf, Sep const& sep, std::tuple< Types... > const& tp)
  {
      size_t num = to_chars(buf, std::cref(std::get<0>(tp)));
      buf  = buf.len >= num ? buf.sub(num) : substr{};
      num += detail::tuple_helper< 1, Types... >::do_catsep_more(buf, sep, tp);
      return num;
  }
  
  template< class Sep, class... Types >
  inline size_t uncatsep(csubstr buf, Sep & sep, std::tuple< Types... > & tp)
  {
      size_t ret = from_str_trim(buf, &std::get<0>(tp)), num = ret;
      if(ret == csubstr::npos) return csubstr::npos;
      buf  = buf.len >= ret ? buf.sub(ret) : substr{};
      ret  = detail::tuple_helper< 1, Types... >::do_uncatsep_more(buf, sep, tp);
      if(ret == csubstr::npos) return csubstr::npos;
      num += ret;
      return num;
  }
  
  template< class... Types >
  inline size_t format(substr buf, csubstr fmt, std::tuple< Types... > const& tp)
  {
      return detail::tuple_helper< 0, Types... >::do_format(buf, fmt, tp);
  }
  
  template< class... Types >
  inline size_t unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp)
  {
      return detail::tuple_helper< 0, Types... >::do_unformat(buf, fmt, tp);
  }
  #endif // C4_TUPLE_TO_CHARS
  
  } // namespace c4
  
  #endif /* _C4_STD_TUPLE_HPP_ */
  