Variadic 模板函数 - 放在哪里

Variadic template functions - where to put base case

我想创建一个将参数保存到容器中的函数。

这确实有效:

template <size_t idx, class TargetT, class HeadU>
void variadicFill(TargetT& target, HeadU head)
{
    target[idx]               = head;
}
template <size_t idx ,class TargetT, class HeadU, class... TailUs>
void variadicFill(TargetT& target, HeadU head, TailUs... tail)
{
    target[idx]               = head;
    variadicFill<idx+1ULL>(target, tail...);
}

但这不是:

template <size_t idx ,class TargetT, class HeadU, class... TailUs>
void variadicFill(TargetT& target, HeadU head, TailUs... tail)
{
    target[idx]               = head;
    variadicFill<idx+1ULL>(target, tail...);
}
template <size_t idx, class TargetT, class HeadU>
void variadicFill(TargetT& target, HeadU head)
{
    target[idx]               = head;
}

错误信息:

<source>: In instantiation of 'void variadicFill(TargetT&, HeadU, TailUs ...) [with long unsigned int idx = 3; TargetT = std::array<int, 4>; HeadU = int; TailUs = {}]':
<source>:11:27:   recursively required from 'void variadicFill(TargetT&, HeadU, TailUs ...) [with long unsigned int idx = 1; TargetT = std::array<int, 4>; HeadU = int; TailUs = {int, int}]'
<source>:11:27:   required from 'void variadicFill(TargetT&, HeadU, TailUs ...) [with long unsigned int idx = 0; TargetT = std::array<int, 4>; HeadU = int; TailUs = {int, int, int}]'
<source>:26:26:   required from here
<source>:11:27: error: no matching function for call to 'variadicFill<(3 + 1)>(std::array<int, 4>&)'
   11 |     variadicFill<idx+1ULL>(target, tail...);
      |     ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
<source>:8:6: note: candidate: 'template<long unsigned int idx, class TargetT, class HeadU, class ... TailUs> void variadicFill(TargetT&, HeadU, TailUs ...)'
    8 | void variadicFill(TargetT& target, HeadU head, TailUs... tail)
      |      ^~~~~~~~~~~~
<source>:8:6: note:   template argument deduction/substitution failed:
<source>:11:27: note:   candidate expects at least 2 arguments, 1 provided
   11 |     variadicFill<idx+1ULL>(target, tail...);
      |     ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~

基本案例必须放在第一位吗?为什么?

谢谢

第二个不起作用,因为您正试图调用其声明对该作用域不可见的重载。您可以像这样对基本情况使用前向声明:

template <size_t idx, class TargetT, class HeadU>
void variadicFill(TargetT& target, HeadU head);

template <size_t idx ,class TargetT, class HeadU, class... TailUs>
void variadicFill(TargetT& target, HeadU head, TailUs... tail)
{
    target[idx]               = head;
    variadicFill<idx+1ULL>(target, tail...);
}

template <size_t idx, class TargetT, class HeadU>
void variadicFill(TargetT& target, HeadU head)
{
    target[idx]               = head;
}

Godbolt.org

在解析模板的时候,它只“看到”已经解析的内容。所以可变参数函数,如果它是第一个,只能调用自己,当 tail 为空时,它试图调用一个只接受一个参数的版本——目标。但是没有这样的功能。

顺序颠倒后,“基本情况”可见并停止递归。