Search code examples
c++templatesc++11template-specializationpartial-specialization

Template template and partial specialization: a puzzle


Consider the following code:

template<typename>
struct S { };

template<typename, typename>
struct B;

template <typename R, typename... Args, template<class> class C>
struct B<R(Args...), C<R>> {
    void f() { }
};

int main() {
    B<void(), S<void>> b;
    b.f();
}

It compiles and has no problem.
Anyway, whenever one decides to use B, it has to provide two types.
What I'd like to achieve is to default somehow the second parameter (I know, partial specializations do not accept a default for their parameters) and let an user define it's type as B<void()> instead of B<void(), S<void>>.
Unfortunately, because of template template, partial specialization and the dependency existent between the parameters, all together they lead to a puzzle against which I'm struggling since a couple of hours.

Is there any clever solution to do that?
So far, I have been able to solve it with intermediate structures, but I don't like it so much...


Solution

  • Partial specializations don't accept default parameters, but the primary does. You can just add it there:

    template<typename Sig, typename X = S<return_type_t<Sig>>>
    struct B;
    

    Then all you need to do is implement a return type metafunction for a signature. Something like:

    template <class Sig>
    struct return_type;
    
    template <class Sig>
    using return_type_t = typename return_type<Sig>::type;
    
    template <class R, class... Args>
    struct return_type<R(Args...)> {
        using type = R;
    };