Search code examples
c++templatesc++17parameter-pack

expand and fold parameter pack in specific way


#include <string>
#include <string_view>

template<typename... Args>
std::string_view concatenateBuffer(std::string &buffer, Args &&... args){
    static_assert((std::is_constructible_v<std::string_view, Args> && ...));

    buffer.clear();

    (buffer.append(std::forward<Args>(args)), ...);

    return buffer;
}


template<typename ...Ts>
std::string_view concat(std::string s, Ts ...ts){
    return concatenateBuffer(s , (("," , ts) , ...) );
}

#include <iostream>

int main(){
    std::string b;

    std::cout << concat(b, "a") << '\n';
    std::cout << concat(b, "a", "b") << '\n';
}

I have function concatenateBuffer, the version I show here is simplified, but what it do is it appends "strings" (char *, string_view, string) to buffer.

I want to do another function concat that act bit like php function implode, e.g. put separator "," between the "strings".

e.g. if you call :

    concat(b, "a")           ===> "a"
    concat(b, "a", "b")      ===> "a,b"
    concat(b, "a", "b", "c") ===> "a,b,c"

Is this possible to be done with folding parameter pack?


Solution

  • You could break the pack up to be able to insert , between the strings:

    template<class T, class ...Ts>
    std::string& concat(std::string& buffer, T&& t, Ts&&...ts){
         buffer.clear();
    
        buffer.append(std::forward<T>(t)); // first argument, no comma
    
        ((buffer.append(","), 
         buffer.append(std::forward<Ts>(ts))), ...);
         
        return buffer;
    }