Skip to main content
edited title
Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

Did I implement my string formatting code correctly? String-formatting and printing functions

Tweeted twitter.com/#!/StackCodeReview/status/484928988830511104
added 10 characters in body
Source Link
Chris_F
  • 347
  • 2
  • 9
#include <boost/algorithm/string/replace.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#include <utility>
#include <cstdio>

namespace detail
{
    template <int<unsigned N, class T>
    void format_impl(std::string& str, T&& item)
    {
        char find[8];
        snprintf(find, 8, "{%d}", N);
        auto replace = boost::lexical_cast<std::string>(std::forward<T>(item));
        boost::replace_all(str, find, replace);
    }

    template <int<unsigned N, class Head, class... Tail>
    void format_impl(std::string& str, Head&& head, Tail&&... tail)
    {
        detail::format_impl<N>(str, std::forward<Head>(head));
        detail::format_impl<N+1>(str, std::forward<Tail>(tail)...);
    }
}

template <class... Args>
std::string format(const std::string& fmt, Args&&... args)
{
    std::string temp = fmt;
    detail::format_impl<0>(temp, std::forward<Args>(args)...);   
    return temp;
}

template <class... Args>
std::string format(std::string&& fmt, Args&&... args)
{
    std::string temp = std::move(fmt);
    detail::format_impl<0>(temp, std::forward<Args>(args)...);   
    return temp;
}

template <class... Args>
void print(const std::string& fmt, Args&&... args)
{
    std::cout << format(fmt, std::forward<Args>(args)...);
}

template <class... Args>
void print(std::string&& fmt, Args&&... args)
{
    std::cout << format(std::forward<std::string>(fmt), std::forward<Args>(args)...);
}

int main()
{
    print("Hello, {0}! The answer is {1}.\n", "World", 42);
}
#include <boost/algorithm/string/replace.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#include <utility>
#include <cstdio>

namespace detail
{
    template <int N, class T>
    void format_impl(std::string& str, T&& item)
    {
        char find[8];
        snprintf(find, 8, "{%d}", N);
        auto replace = boost::lexical_cast<std::string>(std::forward<T>(item));
        boost::replace_all(str, find, replace);
    }

    template <int N, class Head, class... Tail>
    void format_impl(std::string& str, Head&& head, Tail&&... tail)
    {
        detail::format_impl<N>(str, std::forward<Head>(head));
        detail::format_impl<N+1>(str, std::forward<Tail>(tail)...);
    }
}

template <class... Args>
std::string format(const std::string& fmt, Args&&... args)
{
    std::string temp = fmt;
    detail::format_impl<0>(temp, std::forward<Args>(args)...);   
    return temp;
}

template <class... Args>
std::string format(std::string&& fmt, Args&&... args)
{
    std::string temp = std::move(fmt);
    detail::format_impl<0>(temp, std::forward<Args>(args)...);   
    return temp;
}

template <class... Args>
void print(const std::string& fmt, Args&&... args)
{
    std::cout << format(fmt, std::forward<Args>(args)...);
}

template <class... Args>
void print(std::string&& fmt, Args&&... args)
{
    std::cout << format(std::forward<std::string>(fmt), std::forward<Args>(args)...);
}

int main()
{
    print("Hello, {0}! The answer is {1}.\n", "World", 42);
}
#include <boost/algorithm/string/replace.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#include <utility>
#include <cstdio>

namespace detail
{
    template <unsigned N, class T>
    void format_impl(std::string& str, T&& item)
    {
        char find[8];
        snprintf(find, 8, "{%d}", N);
        auto replace = boost::lexical_cast<std::string>(std::forward<T>(item));
        boost::replace_all(str, find, replace);
    }

    template <unsigned N, class Head, class... Tail>
    void format_impl(std::string& str, Head&& head, Tail&&... tail)
    {
        detail::format_impl<N>(str, std::forward<Head>(head));
        detail::format_impl<N+1>(str, std::forward<Tail>(tail)...);
    }
}

template <class... Args>
std::string format(const std::string& fmt, Args&&... args)
{
    std::string temp = fmt;
    detail::format_impl<0>(temp, std::forward<Args>(args)...);   
    return temp;
}

template <class... Args>
std::string format(std::string&& fmt, Args&&... args)
{
    std::string temp = std::move(fmt);
    detail::format_impl<0>(temp, std::forward<Args>(args)...);   
    return temp;
}

template <class... Args>
void print(const std::string& fmt, Args&&... args)
{
    std::cout << format(fmt, std::forward<Args>(args)...);
}

template <class... Args>
void print(std::string&& fmt, Args&&... args)
{
    std::cout << format(std::forward<std::string>(fmt), std::forward<Args>(args)...);
}

int main()
{
    print("Hello, {0}! The answer is {1}.\n", "World", 42);
}
added 144 characters in body
Source Link
Chris_F
  • 347
  • 2
  • 9

As a small exercise I have written some string formatting and printing functions in C++11. I would like a bit of code review, not so much on the merits of using this over something like std::stringstream or boost::format, but simply whether or not my implementation makes sense. I realize that simply performing string replacements isn't that robust and a more sophisticated version would actually parse the format string. I especially would like to know if my use of things like rvalue references, std::forward, std::move and variadic templates are correct, as these are the main features I was focusing on in this exercise.

As a small exercise I have written some string formatting and printing functions in C++11. I would like a bit of code review, not so much on the merits of using this over something like std::stringstream or boost::format, but simply whether or not my implementation makes sense. I especially would like to know if my use of things like rvalue references, std::forward, std::move and variadic templates are correct, as these are the main features I was focusing on in this exercise.

As a small exercise I have written some string formatting and printing functions in C++11. I would like a bit of code review, not so much on the merits of using this over something like std::stringstream or boost::format, but simply whether or not my implementation makes sense. I realize that simply performing string replacements isn't that robust and a more sophisticated version would actually parse the format string. I especially would like to know if my use of things like rvalue references, std::forward, std::move and variadic templates are correct, as these are the main features I was focusing on in this exercise.

Added boost tag since it is used in the code
Link
user33306
user33306
Loading
deleted 22 characters in body; edited tags
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238
Loading
Source Link
Chris_F
  • 347
  • 2
  • 9
Loading