从模板文件生成代码

Code generation from template file

本文关键字:代码 文件      更新时间:2023-10-16

我编写了一个模板文件,如下所示

Hello ${Name}
I like ${food}

我想写一个c++代码,它使用模板文件作为参考生成以下代码

Hello John
I like Pasta
I like Pasta
I like Pasta

在c++中有办法做到这一点吗?我遇到了"模板",但我不相信。我正在开发的应用程序是跨平台的。(我想在c#中做一些类似字符串模板的东西)

我以前用Boost Spirit写过一个模板扩展'引擎':

    用Boost编译一个简单的解析器。

它真的很通用

  • 支持嵌套扩展
  • 支持递归展开
  • 支持动态扩展(例如,如果您希望根据上下文使用不同的值展开变量)

我刚刚把它适应了你的问题的宏语法。查看Live On Coliru


好的,因为性能似乎是主要目标,下面是一个高度优化的扩展引擎,在基准测试中:

#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();
}

它在~0.775秒内运行2^22(4,194,304)次迭代

请参阅Live On Coliru(其中运行时间约为1.8秒)

标准库具有出色的日常正则表达式解析功能(这正是您所需要的),请查看此处的文档。

如果你从未听说过regex,你需要了解它——这至少是一个概述细节的地方。

或者,如果你关心性能,你的任务就像你描述的那样简单,那么编写你自己的解析器应该非常直接,使用两个流,并在复制到输出流时寻找${转义序列,同时根据需要替换。