HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcppModerate

My own C++ Format function

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
ownfunctionformat

Problem

I've never been satisfied with any of the possible sprintf()-like functions in C++:

  • sprintf() is a C function and it's very unsafe and dangerous to use (undefined behavior all over the place)



  • boost::format is too slow and awkward to use (think of the % syntax)



  • iostream is extremely awkward to use



So I came up with my own. Those are my requirements:

  • Inspired by C#'s format function



  • Must never fail at run time, never crash and never have undefined behavior, no matter what you call it with. Should fail at compile time whenever possible instead.



  • Must be expandable (if you create a class Person, then you can pass a Person object to the function)



  • Must be fast



  • The format string must be easy to localize



  • The format string must not have placeholders whose syntax depends on the argument type (ie, no %s vs %d)



  • Must have a fairly "normal" syntax (no % like boost::format)



I'm interested in reviews on the satisfaction of the requirements above. I'm especially interested in reviews from the end-user perspective and less about the internals of the code (i.e., the code that is hidden from the end user).

A few examples:

// Returns a string containing "Hello my name is Andreas and I'm 22 years old".
Format("Hello my name is {0} and I'm {1} years old.", "Andreas", 22);

// Returns "Hex: 0xA"
Format("Hex: {0:x}", 10);

// Fails to compile: Person is not a built in type and doesn't have any function to convert to string
struct Person {};
Person p;
Format("Person: {0}", p);

// "Person: Andreas Bonini" [Note: if it was {0:abc}, then Person::ToString("abc") would have been called]
struct Person {
   Person(string first, string last) : First(first), Last(last) {}
   string ToString(const string &options) const { return Format("{0} {1}", First, Last); }
   string First, Last;
};
Person p("Andreas", "Bonini");
Format("Person: {0}", p);


These are my unit tests:

```
TEST(Format)
{
CHECK_EQUAL(Format("Testing {0} test {0}{0} test",

Solution

There are some serious portability-issues with the code:

  • You do not have proper header guards. #pragma is non-standard.



  • You do not have proper includes (because of a precompiled header, I presume).



  • Names beginning with an underscore followed by an uppercase letter (e.g. _FinalizeFormat, _FindPlaceholder) are reserved by the compiler.

Context

StackExchange Code Review Q#2182, answer score: 11

Revisions (0)

No revisions yet.