'Get variable value from its name as a string at runtime in C++

I'm trying to reproduce (*) something similar to Python fstring, or at least its format function (and while at it, I'd like to implement something like its "Mini-language").

(*) N.B.: please note that I am aware of the existence of the standard lib's format library, as well as the existence of the {fmt} library; but,

a: neither the g++ (11.2.1) nor the clang++ (12.0.1) that I have on my machine can compile code including <format>, and

b: I don't want to use the excellent {fmt} lib, because I'm precisely trying to do my own thing/thingy.

I'm going to use a string in input to my format object, and any number of additional arguments, like that:

// First, some vars
std::string stef{"Stéphane"};
std::string cpp{"C++"};
int ilu3t{3000};

// Then the big deal
std::string my_fstring = badabwe::format(
    "My name is {stef}, and I love {cpp} {ilu3t} !",
    cpp,
    stef,
    ilu3t
);
// Obviously, only the 1st parameter is positional!
// my_fstring should now be:
// My name is Stephane, and I love C++ 3000 !

That's one of the first problem, I have to solve. I think this process is called reflection (please let me know if it's the case).

Next I need to handle a variable number of arguments; the 1st parameter is the only positional and mandatory one (I'm still trying to find a way to iterate over a parameter pack), but its a subject for another question.



Solution 1:[1]

A function is not aware of name of parameters passed it. The parameter doen't even have to have a name:

  void foo(int x);    // name of the argument is x
  foo(42);            // 42 has no name

As suggested in a comment, if you want some mapping between strings (values to be replaced) and strings (their names) then you can use a map. To avoid the caller to spell out this mapping you can use a macro (usually to be avoided, but for now its the only way to get the name of a variable as a string):

#include <iostream>
#include <string>
#include <unordered_map>

using token_t = std::unordered_map<std::string,std::string>;
std::string format(const std::string& tokenized,const token_t& token) {
    return "test";
}   

#define tokenize(token) { #token , to_string(token) }

using std::to_string;
std::string to_string(const std::string& str) { return str; }

int main() {
    std::string stef{"Stéphane"};
    std::string cpp{"C++"};
    int ilu3t{3000};

    std::string my_fstring = format(
        "My name is {stef}, and I love {cpp} {ilu3t} !",
        {
            tokenize(cpp),
            tokenize(stef),
            tokenize(ilu3t)
        }
    );                
}

I assumed that you can use std::to_string, though there is no std::to_string(const std::string&) hence I added a custom implementation.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1