Merge BasicArgFormatter and ArgFormatter
diff --git a/fmt/format.h b/fmt/format.h
index dd3ac29..26ed0bb 100644
--- a/fmt/format.h
+++ b/fmt/format.h
@@ -1873,7 +1873,7 @@
   }
 }
 
-template <typename Impl, typename Char>
+template <typename Char>
 class ArgFormatterBase {
  private:
   BasicWriter<Char> &writer_;
@@ -2055,9 +2055,9 @@
 };
 }  // namespace internal
 
-/** An argument formatter. */
-template <typename Impl, typename Char>
-class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
+/** The default argument formatter. */
+template <typename Char>
+class ArgFormatter : public internal::ArgFormatterBase<Char> {
  private:
   basic_format_context<Char> &ctx_;
 
@@ -2065,31 +2065,21 @@
   /**
     \rst
     Constructs an argument formatter object.
-    *formatter* is a reference to the main formatter object, *spec* contains
-    format specifier information for standard argument types, and *fmt* points
-    to the part of the format string being parsed for custom argument types.
+    *writer* is a reference to the writer to be used for output,
+    *ctx* is a reference to the formatting context, *spec* contains
+    format specifier information for standard argument types.
     \endrst
    */
-  BasicArgFormatter(BasicWriter<Char> &writer, basic_format_context<Char> &ctx,
-                    FormatSpec &spec)
-  : internal::ArgFormatterBase<Impl, Char>(writer, spec), ctx_(ctx) {}
-
-  using internal::ArgFormatterBase<Impl, Char>::operator();
-
-  /** Formats an argument of a custom (user-defined) type. */
-  void operator()(internal::Arg::CustomValue c) {
-    c.format(&this->writer(), c.value, &ctx_);
-  }
-};
-
-/** The default argument formatter. */
-template <typename Char>
-class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
- public:
-  /** Constructs an argument formatter object. */
   ArgFormatter(BasicWriter<Char> &writer, basic_format_context<Char> &ctx,
                FormatSpec &spec)
-  : BasicArgFormatter<ArgFormatter<Char>, Char>(writer, ctx, spec) {}
+  : internal::ArgFormatterBase<Char>(writer, spec), ctx_(ctx) {}
+
+  using internal::ArgFormatterBase<Char>::operator();
+
+  /** Formats an argument of a custom (user-defined) type. */
+  void operator()(format_arg::CustomValue c) {
+    c.format(&this->writer(), c.value, &ctx_);
+  }
 };
 
 template <typename Char>
@@ -2305,7 +2295,7 @@
   template<typename T>
   void append_float_length(Char *&, T) {}
 
-  template <typename Impl, typename Char_>
+  template <typename Char_>
   friend class internal::ArgFormatterBase;
 
   template <typename Char_>
diff --git a/fmt/printf.h b/fmt/printf.h
index f0adf71..30b8095 100644
--- a/fmt/printf.h
+++ b/fmt/printf.h
@@ -208,15 +208,14 @@
   \endrst
  */
 template <typename Char>
-class PrintfArgFormatter :
-    public internal::ArgFormatterBase<PrintfArgFormatter<Char>, Char> {
+class PrintfArgFormatter : public internal::ArgFormatterBase<Char> {
  private:
   void write_null_pointer() {
     this->spec().type_ = 0;
     this->write("(nil)");
   }
 
-  typedef internal::ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base;
+  typedef internal::ArgFormatterBase<Char> Base;
 
  public:
   /**
@@ -227,7 +226,7 @@
     \endrst
    */
   PrintfArgFormatter(BasicWriter<Char> &writer, FormatSpec &spec)
-  : internal::ArgFormatterBase<PrintfArgFormatter<Char>, Char>(writer, spec) {}
+  : internal::ArgFormatterBase<Char>(writer, spec) {}
 
   using Base::operator();
 
diff --git a/test/custom-formatter-test.cc b/test/custom-formatter-test.cc
index 9c56852..7601aeb 100644
--- a/test/custom-formatter-test.cc
+++ b/test/custom-formatter-test.cc
@@ -14,19 +14,18 @@
 
 // A custom argument formatter that doesn't print `-` for floating-point values
 // rounded to 0.
-class CustomArgFormatter
-  : public fmt::BasicArgFormatter<CustomArgFormatter, char> {
+class CustomArgFormatter : public fmt::ArgFormatter<char> {
  public:
   CustomArgFormatter(fmt::Writer &w, fmt::basic_format_context<char> &ctx,
                      fmt::FormatSpec &s)
-  : fmt::BasicArgFormatter<CustomArgFormatter, char>(w, ctx, s) {}
+  : fmt::ArgFormatter<char>(w, ctx, s) {}
 
-  using fmt::BasicArgFormatter<CustomArgFormatter, char>::operator();
+  using fmt::ArgFormatter<char>::operator();
 
   void operator()(double value) {
     if (round(value * pow(10, spec().precision())) == 0)
       value = 0;
-    fmt::BasicArgFormatter<CustomArgFormatter, char>::operator()(value);
+    fmt::ArgFormatter<char>::operator()(value);
   }
 };
 
diff --git a/test/format-test.cc b/test/format-test.cc
index 2ce9d7f..b8e991b 100644
--- a/test/format-test.cc
+++ b/test/format-test.cc
@@ -1619,17 +1619,16 @@
   EXPECT_EQ("0", fmt::format("{}", A));
 }
 
-class MockArgFormatter :
-    public fmt::internal::ArgFormatterBase<MockArgFormatter, char> {
+class MockArgFormatter : public fmt::internal::ArgFormatterBase<char> {
  private:
   MOCK_METHOD1(call, void (int value));
 
  public:
-  typedef fmt::internal::ArgFormatterBase<MockArgFormatter, char> Base;
+  typedef fmt::internal::ArgFormatterBase<char> Base;
 
   MockArgFormatter(fmt::Writer &w, fmt::format_context &ctx,
                    fmt::FormatSpec &s)
-    : fmt::internal::ArgFormatterBase<MockArgFormatter, char>(w, s) {
+    : fmt::internal::ArgFormatterBase<char>(w, s) {
     EXPECT_CALL(*this, call(42));
   }
 
@@ -1637,7 +1636,7 @@
 
   void operator()(int value) { call(value); }
 
-  void operator()(fmt::internal::Arg::CustomValue) {}
+  void operator()(fmt::format_arg::CustomValue) {}
 };
 
 void custom_vformat(fmt::CStringRef format_str, fmt::format_args args) {
diff --git a/test/ostream-test.cc b/test/ostream-test.cc
index d600714..b46418b 100644
--- a/test/ostream-test.cc
+++ b/test/ostream-test.cc
@@ -58,10 +58,10 @@
   EXPECT_EQ("0", fmt::format("{}", A));
 }
 
-struct TestArgFormatter : fmt::BasicArgFormatter<TestArgFormatter, char> {
+struct TestArgFormatter : fmt::ArgFormatter<char> {
   TestArgFormatter(fmt::Writer &w, fmt::format_context &ctx,
                    fmt::FormatSpec &s)
-    : fmt::BasicArgFormatter<TestArgFormatter, char>(w, ctx, s) {}
+    : fmt::ArgFormatter<char>(w, ctx, s) {}
 };
 
 TEST(OStreamTest, CustomArg) {