I've written a template expansion 'engine' using Boost Spirit before:
It's really versatile
- supports nested expansions
- supports recursive expansions
- supports dynamic expansions (e.g. if you want a variable to be expanded with a different value depending on the context)
I've just adapted it to your question's macro syntax. See it Live On Coliru
Update
Okay, since performance appears to be the primary goal, here's a highly optimized expansion engine, in a benchmark:
#include <string>
#include <sstream>
#include <map>
#include <boost/utility/string_ref.hpp>
template <typename Range>
std::string expand(Range const& key)
{
if (key == "Name")
return "John";
if (key == "food")
return "Pasta";
return "??";
}
#include <iostream>
int main()
{
static const std::string msg_template =
"Hello ${Name}\n"
"I like ${food}\n"
;
std::ostringstream builder;
builder.str().reserve(1024); // reserve ample room, not crucial since we reuse it anyways
for (size_t iterations = 1ul << 22; iterations; --iterations)
{
builder.str("");
std::ostreambuf_iterator<char> out(builder);
for(auto f(msg_template.begin()), l(msg_template.end()); f != l;)
{
switch(*f)
{
case '$' :
{
if (++f==l || *f!='{')
{
*out++ = '$';
break;
}
else
{
auto s = ++f;
size_t n = 0;
while (f!=l && *f != '}')
++f, ++n;
// key is [s,f] now
builder << expand(boost::string_ref(&*s, n));
if (f!=l)
++f; // skip '}'
}
}
default:
*out++ = *f++;
}
}
// to make it slow, uncomment:
// std::cout << builder.str();
}
std::cout << builder.str();
}
It runs 2^22 (4,194,304) iterations in ~0.775s
See it Live On Coliru too (where it runs in ~1.8s).