3
\$\begingroup\$

I use console a lot, so I thought this may help me. It's supposed to be simple, safe, and fast. Any ideas?

http://ideone.com/INXub0

#include <iostream>
using namespace std;

class Console
{
public:
    template<typename ...Args>
    static bool WriteLine(const std::string& format, Args&&... args)
    {
        bool success = write(format.c_str(), std::forward<Args>(args)...);
        std::cout << std::endl;
        return success;
    }

    template <typename ...Args>
    static bool Write(const std::string& format, Args&&... args)
    {
        return write(format.c_str(), std::forward<Args>(args)...);
    }

    template<typename T>
    static void WriteLine(T&& value)
    {
        std::cout << std::forward<T>(value) << std::endl;
    }

    template<typename T>
    static void Write(T&& value)
    {
        std::cout << std::forward<T>(value);
    }

private:
    template<typename ...Args>
    static bool write(const char * format, Args&&... args)
    {
        while (*format)
        {
            if (*format == '{')
            {
                bool found_closing_brace = false;
                short value_position = -1;

                while (*(++format))
                {
                    if (*format == '}')
                    {
                        if (value_position == -1)
                            return false;  // {} is not allowed.

                        write_value(value_position, 0, std::forward<Args>(args)...);
                        found_closing_brace = true;
                        break;
                    }
                    else
                    {
                        if (value_position >= 10)
                            return false; //Only range {0 ~ 99} is allowed. 

                        if (value_position == -1)
                            value_position = *format - '0';
                        else
                            value_position = (value_position * 10) + (*format - '0');
                    }
                }

                if (!found_closing_brace)
                    return false; 

                // Continue back to the main loop. This is required.
                // We need to process the next character, because it could be a '\0' or a '{'
                format++;
                continue;
            }

            std::cout << *format;
            format++;
        }

        return true;
    }

    template<typename T, typename ...Args>
    static void write_value(int x, int i, T&& value, Args&&... values)
    {
        if (i == x)
            std::cout << std::forward<T>(value);
        else
            write_value(x, ++i, std::forward<Args>(values)...);
    }

    static void write_value(int x, int i) { }   
};

int main()
{
    Console::WriteLine("Big {11} Bang {0} Theory {6} [{11}, {12}]",

        "Zero", "One", "Two", "Three", "Four", "Five",
        "Six", "Seven", 8, "Nine", "Teen", 11, 12.5f);

    // your code goes here
    return 0;
}
\$\endgroup\$
1
\$\begingroup\$

You must allow the escape character for { and } otherwise this doesn't works.

Console::WriteLine("int {0}(){ return 0; }", function_name);

Apart from that I would add an override to specify the output stream.

std::ofstream logger("log.err");
Console::WriteLine(logger, "String");

It must be a class? Probably it's only a style issue, but I don't like class with only static methods. I prefer namespace and a console_details namespace for private functions.

\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review! Good job on your first answer. \$\endgroup\$ – SirPython Mar 20 '16 at 13:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.