/// @file /// FormatString functionality #ifndef SOPHUS_FORMATSTRING_HPP #define SOPHUS_FORMATSTRING_HPP #include namespace Sophus { namespace details { // Following: http://stackoverflow.com/a/22759544 template class IsStreamable { private: template static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()); template static auto test(...) -> std::false_type; public: static bool const value = decltype(test(0))::value; }; template class ArgToStream { public: static void impl(std::stringstream& stream, T&& arg) { stream << std::forward(arg); } }; inline void FormatStream(std::stringstream& stream, char const* text) { stream << text; return; } // Following: http://en.cppreference.com/w/cpp/language/parameter_pack template void FormatStream(std::stringstream& stream, char const* text, T&& arg, Args&&... args) { static_assert(IsStreamable::value, "One of the args has no ostream overload!"); for (; *text != '\0'; ++text) { if (*text == '%') { ArgToStream::impl(stream, std::forward(arg)); FormatStream(stream, text + 1, std::forward(args)...); return; } stream << *text; } stream << "\nFormat-Warning: There are " << sizeof...(Args) + 1 << " args unused."; return; } template std::string FormatString(char const* text, Args&&... args) { std::stringstream stream; FormatStream(stream, text, std::forward(args)...); return stream.str(); } inline std::string FormatString() { return std::string(); } } // namespace details } // namespace Sophus #endif //SOPHUS_FORMATSTRING_HPP