【问题标题】:Variadic template functions - where to put base case可变模板函数 - 放置基本案例的位置
【发布时间】:2021-04-23 14:26:18
【问题描述】:

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

这确实有效:

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...);
      |     ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~

必须先出现基本情况吗?为什么?

谢谢

【问题讨论】:

  • 这是使用 CUDA 吗?
  • 是的,我忘了删除标签。虽然与问题无关,但它在 gcc 中的行为确实如此
  • 它不起作用是什么意思?你得到一个编译错误?
  • 我认为编译器会在处理基本情况之前扩展您的递归实例化,因此这不起作用,但我不知道它在标准中的什么地方这么说。
  • 是的,编译错误。见:godbolt.org/z/e1qd63jYh

标签: c++ templates c++14 variadic-templates template-meta-programming


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 嗯,很有趣。我可以以某种方式前向声明模板吗?
    • @jlanik - 你可以先声明然后再定义
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-02
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    相关资源
    最近更新 更多