【发布时间】:2020-07-13 21:02:38
【问题描述】:
我有一个代码,它接受一个函数并根据下面的函数签名执行它:
template <int Num>
struct Value {
int value[Num];
};
struct Executor {
template <int N>
void do_exec(std::vector<Value<N>>& n, void (&func) (Value<N>&)) {
for (auto& item : n)
func(item);
}
template <int N>
void do_exec(std::vector<Value<N>>& n, void (&func) (Value<N>&, int)) {
for (int i = 0; i != n.size(); i++)
func(n[i], i);
}
};
当用户传入以下函数之一时,Executor 运行与其签名匹配的do_exec()。
template <int N>
void f1(Value<N>& item)
{
for (auto& i : item.value) {
i = 123;
}
}
template <int N>
void f2(Value<N>& item, int d)
{
for (auto& i : item.value) {
i = d;
}
}
int main()
{
Executor exec;
std::vector<Value<3>> vec(10);
exec.do_exec(vec, f1);
}
我想扩展这段代码,所以它可以使用 lambda 函数,因为在实际代码中,几乎所有代理都会使用 GENERIC lambdas 调用它。
我尝试用std::function 替换函子,但它失败了,因为 lambda 不是std::function 并且类型推导并没有真正发生。
然后我尝试将两个模板参数和 SFINAE 取出一个与签名不匹配的参数,如下所示:
template <typename Fn, typename T, typename = void>
struct HasIndex : std::false_type {};
template <typename Fn, typename T>
struct HasIndex<Fn, T, std::void_t<std::invoke_result_t<Fn, T&, int>>> : std::true_type {};
struct Executor {
template <int N, typename Fn, std::enable_if_t<!HasIndex<Fn, Value<N>>::value, int> = 1>
void do_exec(std::vector<Value<N>>& n, Fn func) {
for (auto& item : n)
func(item);
}
template <int N, typename Fn, std::enable_if_t<HasIndex<Fn, Value<N>>::value, int> = 1>
void do_exec(std::vector<Value<N>>& n, Fn func) {
for (int i = 0; i != n.size(); i++)
func(n[i], i);
}
};
这也不起作用,因为执行程序将采用的函数始终是模板函数(通用 Lambda)。我不知道如何解决这个问题,感谢任何帮助。
请使用c++14解决方案(我知道invoke_result是c++ 17)
【问题讨论】:
-
如果您的 lambda 是无捕获且不是通用的,您可以将其转换为函数指针。
-
@max66:不幸的是,执行器采用的 lambdas 总是通用的。
标签: c++ c++14 template-meta-programming sfinae