admin管理员组

文章数量:1356104

How can I create a format string using std functions (not the external fmt library), where the format arguments are contained within a std::vector<std::string>.

Something like the following (but this example version doesn't compile):

std::string format(std::string fmt, const std::vector<std::string>& list) {
    return std::vformat(fmt, std::make_format_args(list.begin(), list.end()));
}

How can I create a format string using std functions (not the external fmt library), where the format arguments are contained within a std::vector<std::string>.

Something like the following (but this example version doesn't compile):

std::string format(std::string fmt, const std::vector<std::string>& list) {
    return std::vformat(fmt, std::make_format_args(list.begin(), list.end()));
}
Share Improve this question edited Mar 30 at 23:43 David G 96.9k41 gold badges172 silver badges258 bronze badges asked Mar 30 at 23:28 DessDess 2,68727 silver badges41 bronze badges 3
  • The library is no longer external as of C++20. – PaulMcKenzie Commented Mar 30 at 23:53
  • @PaulMcKenzie: I'm talking about the actual 'fmt' external library, not the C++ format facilities. I obviously showed that in the example code. – Dess Commented Mar 30 at 23:58
  • You can't. If you can at least change to a container with compile-time size, you can do something like this: godbolt./z/earGYsWvT – Intelligent Shade of Blue Commented Mar 31 at 0:58
Add a comment  | 

1 Answer 1

Reset to default 0

I don't think what you are attempting is possible with standard formatting functions. std::format() and friends utilize template parameter packs for their input arguments, and parameter packs can only be constructed at compile-time, not dynamically at runtime.

To do what you want, you will need to manually pull apart the fmt string into replacement and non-replacement substrings, and then build up the output std::string concatenation those substrings, making replacements as needed.

For example, if you have a fmt string "{} {} my name is {}" and a vector {"Hello", "World", "Dess"}, then you would extract the following substrings and then concatenate them together:

"{}" -> "Hello"
" "
"{}" -> "World"
" my name is "
"{}" -> "Dess"

However, note that prior to C++26, std::format() requires a string literal for its fmt parameter. So you can't use std::format() in this case. C++26 will introduce std::runtime_format so you can pass in a std::string/std::string_view constructed at runtime, but in the meantime, you will have to use std::vformat() and std::make_format_args() with single-argument replacements.

Try something like this:

std::string format(const std::string_view &fmt, const std::vector<std::string>& list) {
    std::string result;
    std::string::size_type start = 0, pos, end;
    std::vector<std::string>::size_type idx = 0;
    while ((pos = fmt.find('{', start)) != std::string::npos) {
        if (pos > start) result += fmt.substr(start, pos-start);
        if ((end = fmt.find('}', pos+1)) == std::string::npos) break;
        ++end;
        result += std::vformat(fmt.substr(pos, end-pos), std::make_format_args(list.at(idx++)));
        start = end;
    }
    if (start < fmt.size()) result += fmt.substr(start);
    return result;
}

Live Demo

Obviously, you'll have to make this more robust to support the full syntax that the fmt parameter supports, but this should give you an idea to start with.

本文标签: cMake formatted string with arguments in string vectorStack Overflow