终止 class 模板递归

Terminating class template recursion

我最初有以下递归可变参数模板代码

#include <functional>
#include <iostream>

// end of recursion
void apply(std::function<void()> f, int)
{
    f();
}

// base recursive 
template <typename Head, typename ...Tail>
void apply(std::function<void(Head, Tail...)> f, int i)
{
    auto g = [=](Tail&& ...args)
    {
        f(i, std::forward<Tail>(args)...);
    };

    apply(std::function<void(Tail...)>{g}, ++i);
}

void foo(int a, int b, double c, int d)
{
    std::cout << a << b << c << d << std::endl;
}

int main()
{
    auto f = std::function<void(int, int, double, int)>(foo);
    apply(f, 0);
}

它工作正常,但我必须为 Head=double 添加一个案例,所以我最终使用了部分特化结构

#include <functional>
#include <iostream>

// base recursive case
template <typename Head, typename ...Tail>
struct Apply {
    static void apply(std::function<void(Head, Tail...)> f, int i)
    {
        auto g = [=](Tail&& ...args)
        {
            f(i, std::forward<Tail>(args)...);
        };

        Apply<Tail...>::apply(std::function<void(Tail...)>{g}, ++i);
    }
};

// specialization case for double
template <typename ...Tail>
struct Apply<double, Tail...> {
    static void apply(std::function<void(double, Tail...)> f, int i)
    {
        auto g = [=](Tail&& ...args)
        {
            f(777.0, std::forward<Tail>(args)...);
        };

        Apply<Tail...>::apply(std::function<void(Tail...)>{g}, ++i);
    }
};

// end of recursion
template <>
struct Apply {
    static void apply(std::function<void()> f, int)
    {
        f();
    }
};

void foo(int a, int b, double c, int d)
{
    std::cout << a << b << c << d << std::endl;
}

int main()
{
    auto f = std::function<void(int, int, double, int)>(foo);
    Apply<int, int, double, int>::apply(f, 0);
}

但我似乎无法想出结构的正确 "end of recursion" 版本,当它被称为 Apply<Tail...>::apply(std::function<void(Tail...)>{g}, ++i); 时,其中 Tail... 是空的。

声明结构的方式——template <typename Head, typename ...Tail>——它至少需要一种类型,所以它不能为空,因此我不能结束递归。但是我也不能解除这个要求,因为我需要一种方法来引用 apply 方法中除第一个(即 Tail...)之外的所有类型。

提供一个允许空专业化的主要模板。

template <typename ...Types>
struct Apply;

现在提供两个偏特化:

template <typename ... Tail>
struct Apply<double, Tail...>
{
...
};

template <typename Head, typename ... Tail, typename = std::enable_if_t<!std::is_same<Head, double>::value>>
struct Apply<Head, Tail...>
{
...
};

最后,空特化:

template <>
struct Apply<>
{
...
};