text: //  Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //    http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  // Compared with std::stringstream, there are primary purpose of
  // string::Printf:
  //
  // 1. Type-safe printing, with why and how explained in
  //    http://www.drdobbs.com/stringprintf-a-typesafe-printf-family-fo/184401999.
  //    Implementation includes
  //
  //    https://github.com/c42f/tinyformat
  //    boost::format
  //    std::stringstream
  //
  //    std::stringstream is not convenient enough in many cases.  For example:
  //
  //      std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
  //
  //    boost::format is the most convenient one.  We can have
  //
  //      std::cout << format("%2% %1%") % 36 % 77;
  //
  //    or
  //
  //      format fmter("%2% %1%");
  //      fmter % 36; fmter % 77;
  //      std::cout << fmter.c_str();
  //
  //    But the overloading of % might be overkilling and it would be
  //    more efficient if it can write to std::cout directly.
  //
  //    tinyformat has an interface compatible with the C-printf style,
  //    and it can writes to a stream or returns a std::string:
  //
  //      std::cout << tfm::printf(
  //                  "%s, %s %d, %.2d:%.2d\n",
  //                  weekday, month, day, hour, min);
  //
  //    or
  //
  //      tfm::format(std::cout,
  //                  "%s, %s %d, %.2d:%.2d\n",
  //                  weekday, month, day, hour, min);
  //
  // 2. High-performance -- most printed strings are not too long and
  //    doens't need dynamic memory allocation.  Many StringPrintf
  //    implementations doesn't enforce type-safe, but are
  //    high-performance, including
  //
  //    https://developers.google.com/optimization/reference/base/stringprintf/
  //    https://github.com/adobe/chromium/blob/master/base/stringprintf.h
  //    https://github.com/google/protobuf/blob/master/src/google/protobuf/stubs/stringprintf.h
  //
  // According to
  // https://github.com/c42f/tinyformat#compile-time-and-code-bloat,
  // boost::format runs too slow and results in large executable binary
  // files.  So here we port tinyformat.
  
  #pragma once
  
  #include <iostream>
  #include <sstream>
  #include <string>
  
  #include "tinyformat/tinyformat.h"  // https://github.com/c42f/tinyformat
  
  namespace paddle {
  namespace string {
  
  template <typename... Args>
  void Fprintf(std::ostream& out, const char* fmt, const Args&... args) {
    tinyformat::vformat(out, fmt, tinyformat::makeFormatList(args...));
  }
  
  template <typename... Args>
  std::string Sprintf(const char* fmt, const Args&... args) {
    std::ostringstream oss;
    Fprintf(oss, fmt, args...);
    return oss.str();
  }
  
  template <typename... Args>
  void Printf(const char* fmt, const Args&... args) {
    Fprintf(std::cout, fmt, args...);
  }
  
  }  // namespace string
  }  // namespace paddle
  