Make PrintfFormatter public (#335, #360)
diff --git a/doc/api.rst b/doc/api.rst
index 2cde812..58c3c77 100644
--- a/doc/api.rst
+++ b/doc/api.rst
@@ -125,12 +125,15 @@
 .. doxygenclass:: fmt::ArgFormatter
    :members:
 
-Printf formatting functions
----------------------------
+Printf formatting
+-----------------
 
+The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
 The following functions use `printf format string syntax
 <http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
-a POSIX extension for positional arguments.
+the POSIX extension for positional arguments. Unlike their standard
+counterparts, the ``fmt`` functions are type-safe and throw an exception if an
+argument type doesn't match its format specification.
 
 .. doxygenfunction:: printf(CStringRef, ArgList)
 
@@ -138,6 +141,9 @@
 
 .. doxygenfunction:: sprintf(CStringRef, ArgList)
 
+.. doxygenclass:: fmt::PrintfFormatter
+   :members:
+
 Write API
 =========
 
diff --git a/fmt/format.cc b/fmt/format.cc
index a00a8df..81d09cf 100644
--- a/fmt/format.cc
+++ b/fmt/format.cc
@@ -521,7 +521,7 @@
 
 template void internal::ArgMap<char>::init(const ArgList &args);
 
-template void internal::PrintfFormatter<char>::format(
+template void PrintfFormatter<char>::format(
   BasicWriter<char> &writer, CStringRef format);
 
 template int internal::CharTraits<char>::format_float(
@@ -538,7 +538,7 @@
 
 template void internal::ArgMap<wchar_t>::init(const ArgList &args);
 
-template void internal::PrintfFormatter<wchar_t>::format(
+template void PrintfFormatter<wchar_t>::format(
     BasicWriter<wchar_t> &writer, WCStringRef format);
 
 template int internal::CharTraits<wchar_t>::format_float(
diff --git a/fmt/printf.h b/fmt/printf.h
index d06aca5..e50f1e4 100644
--- a/fmt/printf.h
+++ b/fmt/printf.h
@@ -248,23 +248,34 @@
   PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
   : BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {}
 };
+}  // namespace internal
 
-// A printf formatter.
-template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
-class PrintfFormatter : private FormatterBase {
+/** This template formats data and writes the output to a writer. */
+template <typename Char,
+          typename ArgFormatter = internal::PrintfArgFormatter<Char> >
+class PrintfFormatter : private internal::FormatterBase {
  private:
   void parse_flags(FormatSpec &spec, const Char *&s);
 
   // Returns the argument with specified index or, if arg_index is equal
   // to the maximum unsigned value, the next argument.
-  Arg get_arg(const Char *s,
+  internal::Arg get_arg(
+      const Char *s,
       unsigned arg_index = (std::numeric_limits<unsigned>::max)());
 
   // Parses argument index, flags and width and returns the argument index.
   unsigned parse_header(const Char *&s, FormatSpec &spec);
 
  public:
+  /**
+   \rst
+   Constructs a ``PrintfFormatter`` object. References to the arguments
+   are stored in the formatter object so make sure they have appropriate
+   lifetimes.
+   \endrst
+   */
   explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {}
+
   FMT_API void format(BasicWriter<Char> &writer,
                       BasicCStringRef<Char> format_str);
 };
@@ -296,10 +307,11 @@
 }
 
 template <typename Char, typename AF>
-Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, unsigned arg_index) {
+internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
+                                                 unsigned arg_index) {
   (void)s;
   const char *error = 0;
-  Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
+  internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
     next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
   if (error)
     FMT_THROW(FormatError(!*s ? "invalid format string" : error));
@@ -314,7 +326,7 @@
   if (c >= '0' && c <= '9') {
     // Parse an argument index (if followed by '$') or a width possibly
     // preceded with '0' flag(s).
-    unsigned value = parse_nonnegative_int(s);
+    unsigned value = internal::parse_nonnegative_int(s);
     if (*s == '$') {  // value is an argument index
       ++s;
       arg_index = value;
@@ -332,10 +344,10 @@
   parse_flags(spec, s);
   // Parse width.
   if (*s >= '0' && *s <= '9') {
-    spec.width_ = parse_nonnegative_int(s);
+    spec.width_ = internal::parse_nonnegative_int(s);
   } else if (*s == '*') {
     ++s;
-    spec.width_ = WidthHandler(spec).visit(get_arg(s));
+    spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
   }
   return arg_index;
 }
@@ -365,16 +377,17 @@
     if (*s == '.') {
       ++s;
       if ('0' <= *s && *s <= '9') {
-        spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
+        spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s));
       } else if (*s == '*') {
         ++s;
-        spec.precision_ = PrecisionHandler().visit(get_arg(s));
+        spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
       }
     }
 
+    using internal::Arg;
     Arg arg = get_arg(s, arg_index);
-    if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
-      spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
+    if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
+      spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
     if (spec.fill_ == '0') {
       if (arg.type <= Arg::LAST_NUMERIC_TYPE)
         spec.align_ = ALIGN_NUMERIC;
@@ -383,6 +396,7 @@
     }
 
     // Parse length and convert the argument to the required type.
+    using internal::ArgConverter;
     switch (*s++) {
     case 'h':
       if (*s == 'h')
@@ -426,7 +440,7 @@
         break;
       case 'c':
         // TODO: handle wchar_t
-        CharConverter(arg).visit(arg);
+        internal::CharConverter(arg).visit(arg);
         break;
       }
     }
@@ -438,11 +452,10 @@
   }
   write(writer, start, s);
 }
-}  // namespace internal
 
 template <typename Char>
 void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
-  internal::PrintfFormatter<Char>(args).format(w, format);
+  PrintfFormatter<Char>(args).format(w, format);
 }
 
 /**
diff --git a/test/custom-formatter-test.cc b/test/custom-formatter-test.cc
index 9adf8a0..443721e 100644
--- a/test/custom-formatter-test.cc
+++ b/test/custom-formatter-test.cc
@@ -53,7 +53,7 @@
 
 std::string custom_sprintf(const char* fstr, fmt::ArgList args){
   fmt::MemoryWriter writer;
-  fmt::internal::PrintfFormatter< char, CustomPAF > pfer( args);
+  fmt::PrintfFormatter<char, CustomPAF> pfer( args);
   pfer.format(writer, fstr);
   return writer.str();
 }