gpt4 book ai didi

c++ - 具有空参数包的递归可变参数模板(以避免基本情况的重复)

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:17:42 26 4
gpt4 key购买 nike

我正在试验 C++ 递归模板,但我不知道为什么我的模板不起作用。

假设我想定义一个递归函数,它接受可变数量的参数(针对不同类型)。

我看过很多可变参数模板的示例,到目前为止我所看到的所有示例都使用单独的模板特化来指定基本情况。

但是,我认为使用单个模板会更好(至少在某些情况下),它定义了基本情况和递归情况。

我认为如果您在函数中有很多通用逻辑,我认为这种方法特别好,您必须为您的基本案例实例复制这些逻辑(在两个不同的地方使用完全相同的代码)。

下面示例中的第二个模板应该是我的解决方案。我认为这个模板应该可以独立运行。然而,事实并非如此。

没有第一个模板,代码无法编译:

error: no matching function for call to
'add_elems'
return head[i] + add_elems(i, second, tail...);
^~~~~~~~~
in instantiation of function
template specialization 'add_elems<double, std::__1::vector<double, std::__1::allocator<double> >>' requested here

...

显然模板在 tail 时停止运行仅包含一个参数。但不应该add_elems(i, second, tail...)那么仍然对模板有效 template<typename V, typename S, typename... T>
V add_elems(size_t i, const std::vector<V>& head, const S& second, const T&... tail)
空的 tail

我不知道这是否依赖于编译器,但我正在使用 clang。

#include <iostream>
#include <vector>

/* This template is the exact same as the below template with an
empty parameter pack as tail. I want my code to be working
without this specialisation */
template<typename V, typename S>
V add_elems(size_t i, const std::vector<V>& head, const S& second)
{
/* Imagine some more code here */
return head[i] + second[i];
}

template<typename V, typename S, typename... T>
V add_elems(size_t i, const std::vector<V>& head, const S& second, const T&... tail)
{
/* Imagine some more code here (the same as above) */

if (sizeof...(tail) > 0)
return head[i] + add_elems(i, second, tail...);
else
return head[i] + second[i];
}

int main()
{
std::vector<double> a({1, -3, -3});
std::vector<double> b({2, -2, 1});
std::vector<double> c({4, -4, -11});
std::vector<double> d({4, 10, 0});

std::cout << "Result: " << add_elems(0, a, b, c, d);
std::cout << " ," << add_elems(1, a, b, c, d);
std::cout << " ," << add_elems(2, a, b, c, d);
}

最佳答案

问题是你的 if声明不是constexpr .这意味着对于 add_elems 的每个潜在调用,所有代码路径都需要是可编译的。

这意味着您最终会遇到 tail 的情况只是一个元素,编译器需要评估 add_elems(size_t&, const, std::vector<double>&) ,它不存在,因为没有 second争论。

如果您能够拥有一个 constexpr if 声明,那么这一切都会很好地工作,因为编译器甚至不会编译错误的分支,当它评估为 false 时,因此不会寻找不存在的函数:

template<typename V, typename S, typename... T>
V add_elems(size_t i, const std::vector<V>& head, const S& second, const T&... tail)
{
if constexpr (sizeof...(tail) > 0)
return head[i] + add_elems(i, second, tail...);
else
return head[i] + second[i];
}

Demo (需要 Clang 3.9.1 或更高版本和 -std=c++1z 选项。)

就其值(value)而言,如果您可以访问 C++17,则可以使用 unary right fold 实现此目的:

template<typename... T>
decltype(auto) add_elems(size_t i, const T&... elems)
{
return (elems[i] + ...);
}

Demo 2 (需要 Clang 3.6.0 或更高版本和 -std=c++1z 选项。)

关于c++ - 具有空参数包的递归可变参数模板(以避免基本情况的重复),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43277661/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com