Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ variadic parameter join path

Tags:

c++

I try to write a join path function with variadic template. Here's how i do it:

template<typename T>
T&& join_path (T&& path) {
    return path;
}

template<typename T, typename ... Args>
std::string join_path (T&& path1, Args&& ... paths)
{
    static_assert(std::is_same<typename std::decay<T>::type, std::string>::value ||
                  std::is_same<typename std::decay<T>::type, const char *>::value,
                  "T must be a basic_string");

    std::string p2 = join_path(std::forward<Args>(paths)...);
    if (!p2.empty() && p2[0] == '/')
        return path1 + p2;

    return path1 + '/' + p2;
}

But there's a problem, when I pass string literal like join_path("system", path) the T is consider as const char *. So I can't use +operator. How can I fix it?

One fix I think of is return std::string(path1) + '/' + p2;. But wouldn't it introduce extra copying?

like image 766
xubury Avatar asked Aug 27 '26 22:08

xubury


1 Answers

You might use std::string_view since C++17:

std::string join_path(std::initializer_list<std::string_view> paths)
{
    std::string res;
    const char* sep = "";
    for (auto p : paths) {
        res += (!p.empty() && p[0] == '/') ? "" : sep
        res += p;
        sep = "/";
    }
    return res;
}

template<typename ... Ts>
std::string join_path (Ts&&... paths)
{
    static_assert(((std::is_same<typename std::decay<Ts>::type, std::string>::value ||
                  std::is_same<typename std::decay<Ts>::type, const char *>::value) || ...),
                  "T must be a basic_string");
    return join_path({paths...});
}

Demo

like image 98
Jarod42 Avatar answered Aug 30 '26 13:08

Jarod42