I’m using Visual Studio 2008, and I want to implement string formatting function without Variable Argument List.
How to implement “Variadic Template” with pre-c++0x(VS2008)?
Is there any library which implements this like boost?
Or another way to implement this?
Here is my sample code.
(of course, this can’t be complied because i’m using VS2008.)
bool VarPrint(std::ostringstream& out, const std::string& s)
{
std::string::size_type offset = 0;
if((offset = s.find("%")) != std::string::npos)
{
if(!(offset != s.size() - 1 && s[offset + 1] == '%'))
{
ASSERT(!"Missing Arguments!");
return false;
}
}
out << s;
return true;
}
template<typename T, typename... Args>
bool VarPrint(std::ostringstream& out, const std::string& s, const T& value, const Args&... args)
{
std::string::size_type prev_offset = 0;
std::string::size_type curr_offset = 0;
while((curr_offset = s.find("%", prev_offset)) != std::string::npos)
{
out << s.substr(prev_offset, curr_offset);
if(!(curr_offset != s.size() - 1 && s[curr_offset + 1] == '%'))
{
out << value;
if(curr_offset + 2 < s.length())
return VarPrint(out, s.substr(curr_offset + 2), args...); return true;
}
prev_offset = curr_offset + 2;
if(prev_offset >= s.length)
break;
}
ASSERT(!"Extra Argument Provided!");
return false;
}
In C++03, you have different possibilities:
cons(1)("some string")(foo))operator()for example, oroperator%like Boost.Format)The first option is a bit tricky, I feel, because not everyone can understand macros easily, so I would only reserve it for short-terms solutions if you plan on migrating to C++0x soon.
The third option may provide a nice custom touch (formatting is done with a
%sign in many languages), but it also means that one needs to remember how this particular “variadic” function works each time.My personal preference is the
consapproach because it solves both issues:For example, here is how it could work:
The includes that this example will use:
A helper for the result type of appending a value (it could be more efficient with prepending, but that would mean passing the arguments in reverse order which is counter-intuitive):
The
Constemplate itself, with a magicoperator()to append value. Note that it creates a new item with a different type:A revisited
VarPrintwith it:And the demo:
Output: