Reputation: 44043
I am using libfmt to build a code generator that generates a sort of adapter layer around an existing library. So I have a dataset of parameter descriptions that include format strings describing the conversion from the data type in the outer layer to the data type in the inner layer. In the most simple case, this might look like
"{type_out} {var_out} = {var_in};\n"
in a more complex case, the conversion might depend on another parameter:
"int {var_out} = function_call({var_in}, {dependent_param__var_out});\n"
The name dependent_param
(and as such any name that refers to one of its attributes, such as dependent_param__var_out
) is not known to the code generator at compile time; it's constructed at runtime from the parameter dataset.
This means that I need to build a fmt::dynamic_format_arg_store
some of whose named arguments are constructed at runtime. In essence, what I would like is along the lines of
#include <fmt/args.h>
#include <fmt/format.h>
#include <string>
fmt::dynamic_format_arg_store<fmt::format_context>
construct_arg_store(std::string const ¶mname) {
fmt::dynamic_format_arg_store<fmt::format_context> fmt_args;
// so far, so good.
fmt_args.push_back(fmt::arg("var_in", paramname));
fmt_args.push_back(fmt::arg("var_out", paramname + "_out"));
// imagine this were constructed by iterating over runtime-available data.
std::string argname = "dependent_param__var_out";
std::string argvalue = "dependent_param_out";
// Does not compile; fmt::arg expects char const *
fmt_args.push_back(fmt::arg(argname, argvalue));
return fmt_args;
}
int main() {
std::string fmtstring = "int {var_out} = function_call({var_in}, {dependent_param__var_out});\n";
auto args = construct_arg_store("foo");
fmt::vprint(fmtstring, args);
}
Right now, I build a symbol table from the dataset that contains std::string
objects for all possible format arg names and use their .c_str()
to build the fmt::arg
objects (so that the generated C strings have a long enough lifetime). This works, but it seems like a bit of a dirty hack.
So I'm wondering, is there a better way to do it than that?
Upvotes: 1
Views: 318
Reputation: 55594
In general, it's better to use a template system like Mustache for this. That said, storing argument names as std::string
s on the side and use them to construct dynamic_format_arg_store
is OK. There is nothing hacky about it.
Upvotes: 1