Search code examples
c++templatesc++20variadic-templatesc++23

What are different ways of specifying a C++ template types in a structure declaration?


So I was learning template meta programming and came across a declaration like this.

template<class> struct S;
template<class R, class...A> struct S<R(A...)>;

So I was wondering what are the different ways to specify the typenames in angular brackets after identifier. So I tried different combinations of declaring a structure. I tried googling but that didn't solve this issue as I didn't know what to google exactly. Or if there's a resource(blog, SO Answer) for this, please point me to it.

template<class> struct S;
// template<class A> struct S<A>; // 1. does not work
// template<class A, class B> struct S<A, B>; // 2. does not work
template<class A, class B> struct S<A(B)>;
template<class A, class ... B> struct S<A(B...)>;
template<class A, class ... B, class C> struct S<A(B..., C)>;
template<class A, class B, class ... C> struct S<A(B, C...)>;
template<class A, class ... B, class ... C> struct S<A(B..., C...)>;
template<class A, class ... B, class ... C, class D> struct S<A(B..., D, C...)>;

// template<class A, class ... B> struct S<B..., A>; // 3. does not work
// template<class A, class ... B> struct S<A, B...>; // 4. does not work
template<class A, class B, class C, class D> struct S<A(B(C(D)))>;
template<class A, class B, class C, class D> struct S<A(B(C, D))>;
template<class A, class B, class C, class D> struct S<A(B, C(D))>;
template<class A, class B, class C, class D> struct S<A(B(D), C)>;
template<class A, class B, class C, class D> struct S<A(B, C, D)>;

int main() {
    return 0;
}

Solution

  • Good sources to learn C++ are learncpp.com which is a tutorial collection and of course cppreference.com, the full language and standard library reference.

    template<class> struct S;
    template<class R, class...A> struct S<R(A...)>;
    

    The first line is a template class declaration. The second line is a specialization of this template, in case the type S is a function that receives any number of arguments of any type, and returns any type R.

    #include <iostream>
    
    // standard implementation
    template<class>
    struct S {
        static constexpr auto value = 1;
    };
    
    // full specialization
    template <>
    struct S<bool> {
        static constexpr auto value = 2;
    };
    
    // partitial specialization for all functions
    template<class R, class ... A>
    struct S<R(A...)> {
        static constexpr auto value = 3;
    };
    
    int main(){
        std::cout << S<int>::value << " S<int>::value\n";
        std::cout << S<float>::value << " S<float>::value\n";
        std::cout << S<bool>::value << " S<bool>::value\n";
        std::cout << S<void()>::value << " S<void()>::value\n";
        std::cout << S<int()>::value << " S<int()>::value\n";
        std::cout << S<int(float, char, bool)>::value << " S<int(float, char, bool)>::value\n";
    }
    

    does print

    1 S<int>::value
    1 S<float>::value
    2 S<bool>::value
    3 S<void()>::value
    3 S<int()>::value
    3 S<int(float, char, bool)>::value