终止类模板递归

时间:2015-02-17 00:16:47

标签: c++ templates c++11 variadic-templates

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

#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);
}

但我似乎无法想出正确的#34;结束递归&#34;结构的版本,当它被称为Apply<Tail...>::apply(std::function<void(Tail...)>{g}, ++i);时,Tail...为空。

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

1 个答案:

答案 0 :(得分:1)

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

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<>
{
...
};