终止 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<>
{
...
};
我最初有以下递归可变参数模板代码
#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<>
{
...
};