Search code examples
c++templatesparameter-pack

about c++ templates and parameter pack


template<class... Cs>
void func(Cs... cs){
};
template<class T, class... Cs>

void func1(T s){

    func<Cs...>(/* the problem */);
};

int main(){
    char s[]="HI THERE!";
    func1<char*,char,char,char>(s);
    return 0;
}

so the func1() call the func(), the two functions are specialized by the same template parameter pack, the function func1() take a known parameter "s" and we assume that it can produce and provide the parameters values from that s to the func() , but how can we do that.

the problem is hard to me to explain i hope u get the point.

edit: lets say that the args that the func1() passes to func() follow this pattern s[0],s[1],... , is depend on the parameter pack actually


Solution

  • If I understand it correctly, you want to use the parameter pack and expand those number of elements in s:

    #include <cstddef>
    #include <utility>
    
    template<class... Cs>
    void func(Cs&&... cs){ // 'H', 'I', ' '
    };
    
    template<class T, std::size_t... I>
    void func1_helper(T s, std::index_sequence<I...>) {
        func(s[I]...);
    }
    
    template<class T, class... Cs>
    void func1(T s){
        func1_helper(s, std::make_index_sequence<sizeof...(Cs)>{});
    };
    
    int main(){
        char s[]="HI THERE!";
        func1<char*, char,char,char>(s);
        return 0;
    }
    

    As you can see here, the actual types in the pack isn't needed. You could just as easily have supplied the number 3:

    #include <cstddef>
    #include <utility>
    
    template<class... Cs>
    void func(Cs&&... cs){ // 'H', 'I', ' '
    };
    
    template<class T, std::size_t... I>
    void func1_helper(T s, std::index_sequence<I...>) {
        func(s[I]...);
    }
    
    template<std::size_t N, class T>
    void func1(T s){
        func1_helper(s, std::make_index_sequence<N>{});
    };
    
    int main(){
        char s[]="HI THERE!";
        func1<3>(s);
        return 0;
    }
    

    If you really want to pass a pack of types that are not exact matches to what you've got in your array:

    #include <cstddef>
    #include <utility>
    #include <iostream>
    
    template<class... Cs>
    void func(Cs... cs){ // 'H', 'I', ' '
        // prints HI and the `int` value of ' ' (32 most likely):
        (..., (std::cout << cs));
    };
    
    template<class... Cs, class T, std::size_t... I>
    void func1_helper(T s, std::index_sequence<I...>) {
        func<Cs...>(s[I]...);
    }
    
    template<class T, class... Cs>
    void func1(T s){
        func1_helper<Cs...>(s, std::make_index_sequence<sizeof...(Cs)>{});
    };
    
    int main(){
        char s[]="HI THERE!";
        func1<char*, char,char,int>(s);
        return 0;
    }
    
    • std::make_index_sequence<sizeof...(Cs)>{} creates an object of type std::index_sequence<0, 1, 2> (in this case).
    • In func1_helper the indices, 0, 1, 2 goes into the parameter pack size_t... I to match the anonymous index_sequence<I...> argument.
    • I is then used to expand s[I]... into s[0], s[1], s[2].