最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Make formatted string with arguments in string vector - Stack Overflow

programmeradmin3浏览0评论

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.

发布评论

评论列表(0)

  1. 暂无评论