More iteratification
diff --git a/include/fmt/core.h b/include/fmt/core.h
index 8959dac..686494e 100644
--- a/include/fmt/core.h
+++ b/include/fmt/core.h
@@ -624,7 +624,7 @@
     typename Context::template formatter_type<T> f;
     auto &&parse_ctx = ctx.parse_context();
     parse_ctx.advance_to(f.parse(parse_ctx));
-    f.format(*static_cast<const T*>(arg), ctx);
+    ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));
   }
 };
 
@@ -788,23 +788,23 @@
   }
 };
 
-template <typename Range, typename Context>
+template <typename OutputIt, typename Context, typename Char>
 class context_base {
  public:
-  using iterator = decltype(std::declval<Range>().begin());
+  using iterator = OutputIt;
 
  private:
-  basic_parse_context<typename Range::value_type> parse_context_;
+  basic_parse_context<Char> parse_context_;
   iterator out_;
   basic_format_args<Context> args_;
 
  protected:
-  using char_type = typename Range::value_type;
+  using char_type = Char;
   using format_arg = basic_arg<Context>;
 
-  context_base(Range r, basic_string_view<char_type> format_str,
+  context_base(OutputIt out, basic_string_view<char_type> format_str,
                basic_format_args<Context> args)
-  : parse_context_(format_str), out_(r.begin()), args_(args) {}
+  : parse_context_(format_str), out_(out), args_(args) {}
 
   basic_format_args<Context> args() const { return args_; }
 
@@ -824,7 +824,7 @@
   }
 
  public:
-  constexpr basic_parse_context<char_type> &parse_context() {
+  basic_parse_context<char_type> &parse_context() {
     return parse_context_;
   }
 
@@ -882,24 +882,22 @@
 };
 
 // Formatting context.
-template <typename Range>
+template <typename OutputIt, typename Char>
 class basic_context :
-  public internal::context_base<Range, basic_context<Range>> {
+  public internal::context_base<OutputIt, basic_context<OutputIt, Char>, Char> {
  public:
   /** The character type for the output. */
-  using char_type = typename Range::value_type;
+  using char_type = Char;
 
   template <typename T>
   using formatter_type = formatter<T, char_type>;
 
-  using range_type = Range;
-
  private:
   internal::arg_map<basic_context> map_;
 
   FMT_DISALLOW_COPY_AND_ASSIGN(basic_context);
 
-  using base = internal::context_base<Range, basic_context>;
+  using base = internal::context_base<OutputIt, basic_context, Char>;
   using format_arg = typename base::format_arg;
   using base::get_arg;
 
@@ -912,9 +910,9 @@
    stored in the object so make sure they have appropriate lifetimes.
    \endrst
    */
-  basic_context(Range range, basic_string_view<char_type> format_str,
+  basic_context(OutputIt out, basic_string_view<char_type> format_str,
                 basic_format_args<basic_context> args)
-    : base(range, format_str, args) {}
+    : base(out, format_str, args) {}
 
   format_arg next_arg() {
     return this->do_get_arg(this->parse_context().next_arg_id());
@@ -926,8 +924,10 @@
   format_arg get_arg(basic_string_view<char_type> name);
 };
 
-using context = basic_context<back_insert_range<internal::buffer>>;
-using wcontext = basic_context<back_insert_range<internal::wbuffer>>;
+using context = basic_context<
+  std::back_insert_iterator<internal::buffer>, char>;
+using wcontext = basic_context<
+  std::back_insert_iterator<internal::wbuffer>, wchar_t>;
 
 template <typename Context, typename ...Args>
 class arg_store {
@@ -1087,12 +1087,10 @@
   return internal::named_arg<T, wchar_t>(name, arg);
 }
 
-// The following two functions are deleted intentionally to disable
-// nested named arguments as in ``format("{}", arg("a", arg("b", 42)))``.
-template <typename T>
-void arg(string_view, internal::named_arg<T, char>) FMT_DELETED;
-template <typename T>
-void arg(wstring_view, internal::named_arg<T, wchar_t>) FMT_DELETED;
+// This function template is deleted intentionally to disable nested named
+// arguments as in ``format("{}", arg("a", arg("b", 42)))``.
+template <typename S, typename... T>
+void arg(S, internal::named_arg<T...>) FMT_DELETED;
 
 enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
 
diff --git a/include/fmt/format.h b/include/fmt/format.h
index 40e3c7b..6ffae2d 100644
--- a/include/fmt/format.h
+++ b/include/fmt/format.h
@@ -2058,10 +2058,12 @@
 template <typename Range>
 class arg_formatter: public internal::arg_formatter_base<Range> {
  private:
-  basic_context<Range> &ctx_;
-
   using char_type = typename Range::value_type;
+  using iterator = decltype(std::declval<Range>().begin());
   using base = internal::arg_formatter_base<Range>;
+  using context_type = basic_context<iterator, char_type>;
+
+  context_type &ctx_;
 
  public:
   using range = Range;
@@ -2074,13 +2076,13 @@
     *spec* contains format specifier information for standard argument types.
     \endrst
    */
-  arg_formatter(basic_context<Range> &ctx, format_specs &spec)
+  arg_formatter(context_type &ctx, format_specs &spec)
   : base(Range(ctx.begin()), spec), ctx_(ctx) {}
 
   using base::operator();
 
   /** Formats an argument of a custom (user-defined) type. */
-  void operator()(typename basic_arg<basic_context<Range>>::handle handle) {
+  void operator()(typename basic_arg<context_type>::handle handle) {
     handle.format(ctx_);
   }
 };
@@ -2851,7 +2853,8 @@
       specs_.width_, specs_.width_ref, ctx);
     internal::handle_dynamic_spec<internal::precision_checker>(
       specs_.precision_, specs_.precision_ref, ctx);
-    using range = typename FormatContext::range_type;
+    using range = output_range<
+      typename FormatContext::iterator, typename FormatContext::char_type>;
     visit(arg_formatter<range>(ctx, specs_),
           internal::make_arg<FormatContext>(val));
     return ctx.begin();
@@ -2919,7 +2922,9 @@
     }
     if (specs_.precision_ != -1)
       checker.end_precision();
-    visit(arg_formatter<typename FormatContext::range_type>(ctx, specs_),
+    using range = output_range<
+      typename FormatContext::iterator, typename FormatContext::char_type>;
+    visit(arg_formatter<range>(ctx, specs_),
           internal::make_arg<FormatContext>(val));
     return ctx.begin();
   }
@@ -2936,9 +2941,9 @@
   internal::dynamic_format_specs<Char> specs_;
 };
 
-template <typename Range>
-typename basic_context<Range>::format_arg
-  basic_context<Range>::get_arg(basic_string_view<char_type> name) {
+template <typename Range, typename Char>
+typename basic_context<Range, Char>::format_arg
+  basic_context<Range, Char>::get_arg(basic_string_view<char_type> name) {
   map_.init(this->args());
   format_arg arg = map_.find(name);
   if (arg.type() == internal::NONE)
@@ -2957,7 +2962,7 @@
   struct handler : internal::error_handler {
     handler(range r, basic_string_view<Char> str,
             basic_format_args<Context> format_args)
-      : context(r, str, format_args) {}
+      : context(r.begin(), str, format_args) {}
 
     void on_text(iterator begin, iterator end) {
       size_t size = end - begin;
@@ -3089,10 +3094,10 @@
 }
 
 template <typename OutputIt, typename Char = char>
-using context_t = basic_context<output_range<OutputIt, Char>>;
+using context_t = basic_context<OutputIt, Char>;
 
-template <typename OutputIt>
-using format_args_t = basic_format_args<context_t<OutputIt>>;
+template <typename OutputIt, typename Char = char>
+using format_args_t = basic_format_args<context_t<OutputIt, Char>>;
 
 template <typename OutputIt, typename... Args>
 inline void vformat_to(OutputIt out, string_view format_str,
diff --git a/include/fmt/printf.h b/include/fmt/printf.h
index 11d3aee..28630a0 100644
--- a/include/fmt/printf.h
+++ b/include/fmt/printf.h
@@ -201,7 +201,10 @@
 template <typename Range>
 class printf_arg_formatter;
 
-template <typename Range, typename ArgFormatter = printf_arg_formatter<Range>>
+template <
+    typename OutputIt, typename Char,
+    typename ArgFormatter =
+      printf_arg_formatter<back_insert_range<internal::basic_buffer<Char>>>>
 class basic_printf_context;
 
 /**
@@ -212,16 +215,18 @@
 template <typename Range>
 class printf_arg_formatter : public internal::arg_formatter_base<Range> {
  private:
-  basic_printf_context<Range> &context_;
+  using char_type = typename Range::value_type;
+  using iterator = decltype(std::declval<Range>().begin());
+  using base = internal::arg_formatter_base<Range>;
+  using context_type = basic_printf_context<iterator, char_type>;
+
+  context_type &context_;
 
   void write_null_pointer() {
     this->spec().type_ = 0;
     this->write("(nil)");
   }
 
-  using char_type = typename Range::value_type;
-  using base = internal::arg_formatter_base<Range>;
-
  public:
   using format_specs = typename base::format_specs;
 
@@ -233,8 +238,9 @@
     \endrst
    */
   printf_arg_formatter(internal::basic_buffer<char_type> &buffer,
-                       format_specs &spec, basic_printf_context<Range> &ctx)
-  : base(buffer, spec), context_(ctx) {}
+                       format_specs &spec, context_type &ctx)
+    : base(back_insert_range<internal::basic_buffer<char_type>>(buffer), spec),
+      context_(ctx) {}
 
   using base::operator();
 
@@ -276,8 +282,7 @@
   }
 
   /** Formats an argument of a custom (user-defined) type. */
-  void operator()(
-      typename basic_arg<basic_printf_context<Range>>::handle handle) {
+  void operator()(typename basic_arg<context_type>::handle handle) {
     handle.format(context_);
   }
 };
@@ -295,19 +300,19 @@
 };
 
 /** This template formats data and writes the output to a writer. */
-template <typename Range, typename ArgFormatter>
+template <typename OutputIt, typename Char, typename ArgFormatter>
 class basic_printf_context :
   private internal::context_base<
-    Range, basic_printf_context<Range, ArgFormatter>> {
+    OutputIt, basic_printf_context<OutputIt, Char, ArgFormatter>, Char> {
  public:
   /** The character type for the output. */
-  using char_type = typename Range::value_type;
+  using char_type = Char;
 
   template <typename T>
   using formatter_type = printf_formatter<T>;
 
  private:
-  using base = internal::context_base<Range, basic_printf_context>;
+  using base = internal::context_base<OutputIt, basic_printf_context, Char>;
   using format_arg = typename base::format_arg;
   using format_specs = basic_format_specs<char_type>;
   using iterator = internal::null_terminating_iterator<char_type>;
@@ -331,9 +336,9 @@
    appropriate lifetimes.
    \endrst
    */
-  basic_printf_context(Range range, basic_string_view<char_type> format_str,
+  basic_printf_context(OutputIt out, basic_string_view<char_type> format_str,
                        basic_format_args<basic_printf_context> args)
-    : base(range, format_str, args) {}
+    : base(out, format_str, args) {}
 
   using base::parse_context;
   using base::begin;
@@ -343,8 +348,8 @@
   FMT_API void format();
 };
 
-template <typename Range, typename AF>
-void basic_printf_context<Range, AF>::parse_flags(
+template <typename OutputIt, typename Char, typename AF>
+void basic_printf_context<OutputIt, Char, AF>::parse_flags(
     format_specs &spec, iterator &it) {
   for (;;) {
     switch (*it++) {
@@ -370,17 +375,18 @@
   }
 }
 
-template <typename Range, typename AF>
-typename basic_printf_context<Range, AF>::format_arg
-    basic_printf_context<Range, AF>::get_arg(iterator it, unsigned arg_index) {
+template <typename OutputIt, typename Char, typename AF>
+typename basic_printf_context<OutputIt, Char, AF>::format_arg
+  basic_printf_context<OutputIt, Char, AF>::get_arg(
+    iterator it, unsigned arg_index) {
   (void)it;
   if (arg_index == std::numeric_limits<unsigned>::max())
     return this->do_get_arg(this->parse_context().next_arg_id());
   return base::get_arg(arg_index - 1);
 }
 
-template <typename Range, typename AF>
-unsigned basic_printf_context<Range, AF>::parse_header(
+template <typename OutputIt, typename Char, typename AF>
+unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
   iterator &it, format_specs &spec) {
   unsigned arg_index = std::numeric_limits<unsigned>::max();
   char_type c = *it;
@@ -416,8 +422,8 @@
   return arg_index;
 }
 
-template <typename Range, typename AF>
-void basic_printf_context<Range, AF>::format() {
+template <typename OutputIt, typename Char, typename AF>
+void basic_printf_context<OutputIt, Char, AF>::format() {
   auto &buffer = internal::get_container(this->begin());
   auto start = iterator(this->parse_context());
   auto it = start;
@@ -506,8 +512,7 @@
         break;
       case 'c':
         // TODO: handle wchar_t
-        visit(internal::CharConverter<basic_printf_context<Range, AF>>(arg),
-              arg);
+        visit(internal::CharConverter<basic_printf_context>(arg), arg);
         break;
       }
     }
@@ -523,11 +528,12 @@
 template <typename Char, typename Context>
 void printf(internal::basic_buffer<Char> &buf, basic_string_view<Char> format,
             basic_format_args<Context> args) {
-  Context(buf, format, args).format();
+  Context(std::back_inserter(buf), format, args).format();
 }
 
 template <typename Buffer>
-using printf_context = basic_printf_context<back_insert_range<Buffer>>;
+using printf_context = basic_printf_context<
+  std::back_insert_iterator<Buffer>, typename Buffer::value_type>;
 
 using printf_args = basic_format_args<printf_context<internal::buffer>>;