This function formats a string by replacing every occurrence of '{n}' with the corresponding argument that was passed to the function where n is an index that starts at 0. The same index can be used multiple times and the order is irrelevant. If n is out of bounds or cannot be converted to an integer number I just add '{n}' to the result. The function is intended to be used e.g with config files that can be changed by the user where it would be unsafe to use sprintf. The use of std::ostringstream allows me to pass any type that has an overloaded << operator. I was considering using iterators in the loops but I'm not sure whether that would gain anything.
#pragma once
#include <string>
#include <vector>
#include <sstream>
#include <string_view>
namespace util::str{
    inline void to_string_vector(std::vector<std::string>&){} //Dummy used to end recursion
    template<typename T, typename ... Args>
    void to_string_vector(std::vector<std::string>& result, const T& t, Args&& ...args){
        result.push_back((std::ostringstream{} << t).str());
        to_string_vector(result, args...);
    }
    template<typename ... Args>
    std::string format(std::string_view fmt, Args&& ...args){
        std::string result;
        std::vector<std::string> values;
        result.reserve(fmt.size());
        to_string_vector(values, args...);
        for(std::size_t first = 0; first < fmt.size(); ++first){
            if(fmt[first] == '{'){
                for(std::size_t second = first + 1; second < fmt.size(); ++second){
                    if(fmt[second] == '}'){
                        try{
                            std::size_t index = std::stoi(std::string{fmt.substr(first + 1, second - first - 1)});
                            if(index < values.size())
                                result += values[index];
                            else
                                result += fmt.substr(first, second - first + 1);
                        }catch(...){
                            result += fmt.substr(first, second - first + 1);
                        }
                        first = second;
                        break;
                    }else if(fmt[second] == '{'){
                        result += fmt.substr(first, second - first);
                        first = second - 1;
                        break;
                    }
                }
            }else{
                result.push_back(fmt[first]);
            }
        }
        return result;
    }
}
ostream, but it works and looks ok. Any concerns and/or future plans? \$\endgroup\$}and before{when there is something else after/before:} else {andif(fmt[second] == '}') {, maybe after keywords (if (...andfor () but that would be bonus :) \$\endgroup\$