Use named argument emulation instead of nested functions
diff --git a/fmt/format.h b/fmt/format.h
index e6ea86d..9a7a99a 100644
--- a/fmt/format.h
+++ b/fmt/format.h
@@ -1639,6 +1639,52 @@
   CHAR_FLAG = 0x10  // Argument has char type - used in error reporting.
 };
 
+enum format_spec_tag {fill_tag, align_tag, width_tag, type_tag};
+
+// Format specifier.
+template <typename T, format_spec_tag>
+class format_spec {
+ private:
+  T value_;
+
+ public:
+  typedef T value_type;
+
+  explicit format_spec(T value) : value_(value) {}
+
+  T value() const { return value_; }
+};
+
+template <typename Char>
+using fill_spec = format_spec<Char, fill_tag>;
+
+using width_spec = format_spec<unsigned, width_tag>;
+using type_spec = format_spec<char, type_tag>;
+
+class fill_spec_factory {
+ public:
+  constexpr fill_spec_factory() {}
+
+  template <typename Char>
+  fill_spec<Char> operator=(Char value) const {
+    return fill_spec<Char>(value);
+  }
+};
+
+template <typename FormatSpec>
+class format_spec_factory {
+ public:
+  constexpr format_spec_factory() {}
+
+  FormatSpec operator=(typename FormatSpec::value_type value) const {
+    return FormatSpec(value);
+  }
+};
+
+constexpr fill_spec_factory fill;
+constexpr format_spec_factory<width_spec> width;
+constexpr format_spec_factory<type_spec> type;
+
 // An empty format specifier.
 struct EmptySpec {};
 
@@ -1688,15 +1734,40 @@
 };
 
 // A full format specifier.
-struct FormatSpec : AlignSpec {
+class FormatSpec : public AlignSpec {
+ private:
+  void set(fill_spec<char> fill) {
+    fill_ = fill.value();
+  }
+
+  void set(width_spec width) {
+    width_ = width.value();
+  }
+
+  void set(type_spec type) {
+    type_ = type.value();
+  }
+
+  template <typename Spec, typename... Specs>
+  void set(Spec spec, Specs... tail) {
+    set(spec);
+    set(tail...);
+  }
+
+ public:
   unsigned flags_;
   int precision_;
   char type_;
 
-  FormatSpec(
-    unsigned width = 0, char type = 0, wchar_t fill = ' ')
+  FormatSpec(unsigned width = 0, char type = 0, wchar_t fill = ' ')
   : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {}
 
+  template <typename... FormatSpecs>
+  explicit FormatSpec(FormatSpecs... specs)
+    : AlignSpec(0, ' '), flags_(0), precision_(-1), type_(0){
+    set(specs...);
+  }
+
   bool flag(unsigned f) const { return (flags_ & f) != 0; }
   int precision() const { return precision_; }
   char type() const { return type_; }
@@ -1811,13 +1882,6 @@
     TYPE value, unsigned width) { \
   return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \
       value, AlignTypeSpec<0>(width, ' ')); \
-} \
- \
-template <typename Char> \
-inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \
-   TYPE value, unsigned width, Char fill) { \
- return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \
-     value, AlignTypeSpec<0>(width, fill)); \
 }
 
 FMT_DEFINE_INT_FORMATTERS(int)
@@ -2226,6 +2290,17 @@
 FMT_API void format_system_error(fmt::writer &out, int error_code,
                                  fmt::StringRef message) FMT_NOEXCEPT;
 
+namespace internal {
+// Named format specifier.
+template <typename T>
+class named_format_spec {
+ public:
+  constexpr named_format_spec() {}
+};
+
+constexpr named_format_spec<unsigned> width;
+}
+
 /**
   \rst
   This template provides operations for formatting and writing data into
@@ -2309,7 +2384,7 @@
   CharPtr prepare_int_buffer(unsigned num_digits,
     const Spec &spec, const char *prefix, unsigned prefix_size);
 
-  // Formats an integer.
+  // Writes a formatted integer.
   template <typename T, typename Spec>
   void write_int(T value, Spec spec);
 
@@ -2449,6 +2524,12 @@
     *this << IntFormatSpec<ULongLong>(value);
   }
 
+  template <typename T, typename... FormatSpecs>
+  typename std::enable_if<std::is_integral<T>::value, void>::type
+      write(T value, FormatSpecs... specs) {
+    write_int(value, FormatSpec(specs...));
+  }
+
   void write(double value) {
     write_double(value, FormatSpec());
   }