C++ 模板代码自动生成

https://github.com/pantor/inja

#include <inja/inja.hpp>

// Just for convenience

using namespace inja;

void testFile() {

Environment env;

json data;

// Render a string with json data

std::string result = env.render("Hello {{ name }}!", data); // "Hello world!"

// Or directly read a template file

Template temp = env.parse_template("./templates/greeting.txt");

result = env.render(temp, data); // "Hello world!"

data["name"] = "Inja";

result = env.render(temp, data); // "Hello Inja!"

// Or read the template file (and/or the json file) directly from the environment

result = env.render_file("./templates/greeting.txt", data);

result = env.render_file_with_json_file("./templates/greeting.txt", "./data.json");

// Or write a rendered template file

env.write(temp, data, "./result.txt");

env.write_with_json_file("./templates/greeting.txt", "./data.json", "./result.txt");

}

void testFunc() {

Environment env;

json data;

// Upper and lower function, for string cases

render("Hello {{ upper(neighbour) }}!", data); // "Hello PETER!"

render("Hello {{ lower(neighbour) }}!", data); // "Hello peter!"

// Range function, useful for loops

render("{% for i in range(4) %}{{ loop.index1 }}{% endfor %}", data); // "1234"

render("{% for i in range(3) %}{{ at(guests, i) }} {% endfor %}", data); // "Jeff Tom Patrick "

// Length function (please don't combine with range, use list directly...)

render("I count {{ length(guests) }} guests.", data); // "I count 3 guests."

// Get first and last element in a list

render("{{ first(guests) }} was first.", data); // "Jeff was first."

render("{{ last(guests) }} was last.", data); // "Patir was last."

// Sort a list

render("{{ sort([3,2,1]) }}", data); // "[1,2,3]"

render("{{ sort(guests) }}", data); // "[\"Jeff\", \"Patrick\", \"Tom\"]"

// Join a list with a separator

render("{{ join([1,2,3], \" + \") }}", data); // "1 + 2 + 3"

render("{{ join(guests, \", \") }}", data); // "Jeff, Patrick, Tom"

// Round numbers to a given precision

render("{{ round(3.1415, 0) }}", data); // 3

render("{{ round(3.1415, 3) }}", data); // 3.142

// Check if a value is odd, even or divisible by a number

render("{{ odd(42) }}", data); // false

render("{{ even(42) }}", data); // true

render("{{ divisibleBy(42, 7) }}", data); // true

// Maximum and minimum values from a list

render("{{ max([1, 2, 3]) }}", data); // 3

render("{{ min([-2.4, -1.2, 4.5]) }}", data); // -2.4

// Convert strings to numbers

render("{{ int(\"2\") == 2 }}", data); // true

render("{{ float(\"1.8\") > 2 }}", data); // false

// Set default values if variables are not defined

render("Hello {{ default(neighbour, \"my friend\") }}!", data); // "Hello Peter!"

render("Hello {{ default(colleague, \"my friend\") }}!", data); // "Hello my friend!"

// Access an objects value dynamically

render("{{ at(time, \"start\") }} to {{ time.end }}", data); // "16 to 22"

// Check if a key exists in an object

render("{{ exists(\"guests\") }}", data); // "true"

render("{{ exists(\"city\") }}", data); // "false"

render("{{ existsIn(time, \"start\") }}", data); // "true"

render("{{ existsIn(time, neighbour) }}", data); // "false"

// Check if a key is a specific type

render("{{ isString(neighbour) }}", data); // "true"

render("{{ isArray(guests) }}", data); // "true"

// Implemented type checks: isArray, isBoolean, isFloat, isInteger, isNumber, isObject, isString,

}

void testCallback() {

Environment env;

json data;

/*

* Callbacks are defined by its:

* - name,

* - (optional) number of arguments,

* - callback function.

*/

env.add_callback("double", 1, [](Arguments& args) {

int number = args.at(0)->get<int>(); // Adapt the index and type of the argument

return 2 * number;

});

// You can then use a callback like a regular function

env.render("{{ double(16) }}", data); // "32"

// Inja falls back to variadic callbacks if the number of expected arguments is omitted.

env.add_callback("argmax", [](Arguments& args) {

auto result = std::max_element(args.begin(), args.end(), [](const json* a, const json* b) { return *a < *b; });

return std::distance(args.begin(), result);

});

env.render("{{ argmax(4, 2, 6) }}", data); // "2"

env.render("{{ argmax(0, 2, 6, 8, 3) }}", data); // "3"

// A callback without argument can be used like a dynamic variable:

std::string greet = "Hello";

env.add_callback("double-greetings", 0, [greet](Arguments args) {

return greet + " " + greet + "!";

});

env.render("{{ double-greetings }}", data); // "Hello Hello!"

env.add_void_callback("log", 1, [greet](Arguments args) {

std::cout << "logging: " << args[0] << std::endl;

});

env.render("{{ log(neighbour) }}", data); // Prints nothing to result, only to cout...

}

void test() {

json data;

data["name"] = "world";

render("Hello {{ name }}!", data); // Returns std::string "Hello world!"

render_to(std::cout, "Hello {{ name }}!", data); // Writes "Hello world!" to stream

//testFile(); // 文件读写

// With default settings

Environment env_default;

// With global path to template files and where files will be saved

Environment env_1{ "../path/templates/" };

// With separate input and output path

Environment env_2{ "../path/templates/", "../path/results/" };

// With other opening and closing strings (here the defaults)

Environment env;

env.set_expression("{{", "}}"); // Expressions

env.set_comment("{#", "#}"); // Comments

env.set_statement("{%", "%}"); // Statements {% %} for many things, see below

env.set_line_statement("##"); // Line statements ## (just an opener)

// json成员解析

data["neighbour"] = "Peter";

data["guests"] = { "Jeff", "Tom", "Patrick" };

data["time"]["start"] = 16;

data["time"]["end"] = 22;

// Indexing in array

render("{{ guests.1 }}", data); // "Tom"

// Objects

render("{{ time.start }} to {{ time.end + 1 }}pm", data); // "16 to 23pm"

// If no variable is found, valid JSON is printed directly, otherwise an inja::RenderError is thrown.

// Combining loops and line statements

//render(R"(Guest List: ## for guest in guests {{ loop.index1 }}: {{ guest }} ## endfor )", data);

// loop.is_first loop.is_last loop.parent.index {% for key, value in time %}

// Conditions

// Standard comparisons with a variable

render("{% if time.hour >= 20 %}Serve{% else if time.hour >= 18 %}Make{% endif %} dinner.", data); // Serve dinner.

// Variable in list

render("{% if neighbour in guests %}Turn up the music!{% endif %}", data); // Turn up the music!

// Logical operations

render("{% if guest_count < (3+2) and all_tired %}Sleepy...{% else %}Keep going...{% endif %}", data); // Sleepy...

// Negations

render("{% if not guest_count %}The End{% endif %}", data); // The End

// To include in-memory templates, add them to the environment first

inja::Template content_template = env.parse("Hello {{ neighbour }}!");

env.include_template("content", content_template);

env.render("Content: {% include \"content\" %}", data); // "Content: Hello Peter!"

// Other template files are included relative from the current file location

render("{% include \"footer.html\" %}", data);

// The callback takes the current path and the wanted include name and returns a template

env.set_include_callback([&env](const std::string& path, const std::string& template_name) {

return env.parse("Hello {{ neighbour }} from " + template_name);

});

// You can disable to search for templates in the file system via

env.set_search_included_templates_in_files(false); // env.set_throw_at_missing_includes(false)

render("{% set new_hour=23 %}{{ new_hour }}pm", data); // "23pm"

render("{% set time.start=18 %}{{ time.start }}pm", data); // using json pointers

env.set_trim_blocks(true);

env.set_lstrip_blocks(true);

render("Hello{# Todo #}!", data); // "Hello!"

// INJA_NOEXCEPTION

}

// 从模板创建单例类

void createSingletonClass() {

std::string tmplH = "class {{port}} {{name}} \n{\npublic:\n using SP = std::shared_ptr<{{name}}>;\n\n static {{name}} *getInstance();\n static void release();\npublic:\n static {{name}} *m_instance;\n};\n";

std::string tmplCpp = "{{name}} *{{name}}::m_instance = nullptr;\n{{name}} *{{name}}::getInstance(){\n if(!m_instance){\n m_instnace = new {{name}}();\n }\n return m_instance;\n}\n";

std::string tmplCpp2 = "void *{{name}}::release(){\n if(m_instance){\n\tdelete m_instnace; \n }\n m_instance = nullptr;\n}\n";

json data;

data["name"] = "Singleton";

data["port"] = "";

render_to(std::cout, tmplH, data);

render_to(std::cout, tmplCpp + tmplCpp2, data);

}

输出:

class Singleton

{

public:

using SP = std::shared_ptr<Singleton>;

static Singleton *getInstance();

static void release();

public:

static Singleton *m_instance;

};

Singleton *Singleton::m_instance = nullptr;

Singleton *Singleton::getInstance(){

if(!m_instance){

m_instnace = new Singleton();

}

return m_instance;

}

void *Singleton::release(){

if(m_instance){

delete m_instnace;

}

m_instance = nullptr;

}


创作不易,小小的支持一下吧!

相关推荐
半盏茶香28 分钟前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
小堇不是码农34 分钟前
在VScode中配置C_C++环境
c语言·c++·vscode
Jack黄从零学c++37 分钟前
C++ 的异常处理详解
c++·经验分享
捕鲸叉6 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer6 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq6 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
hairenjing11237 小时前
使用 Mac 数据恢复从 iPhoto 图库中恢复照片
windows·stm32·嵌入式硬件·macos·word
青花瓷8 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
九鼎科技-Leo9 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net
幺零九零零9 小时前
【C++】socket套接字编程
linux·服务器·网络·c++