当前位置: 首页 > 知识库问答 >
问题:

演绎指南和可变模板

卢聪
2023-03-14

考虑以下代码:

#include <tuple>
#include <iostream>

template <class T>
struct custom_wrapper
{
    template <class Arg>
    custom_wrapper(Arg arg): data(arg) {}
    T data;
};

template <class Arg>
custom_wrapper(Arg arg) -> custom_wrapper<Arg>;

template <class... T>
struct custom_tuple
{
    template <class... Args>
    custom_tuple(Args... args): data(args...) {}
    std::tuple<T...> data;
};

template <class... Args>
custom_tuple(Args... args) -> custom_tuple<Args...>;

int main(int argc, char* argv[])
{
    custom_wrapper<int> w1(42);  // OK
    custom_wrapper w2(42);       // OK
    custom_tuple<int> t1(42);    // OK
    custom_tuple t2(42);         // Fails
    return 0;
}

失败的行在G7下返回以下错误:

variadic_deduction_guide.cpp: In instantiation of 'custom_tuple<T>::custom_tuple(Args ...) [with Args = {int}; T = {}]':
variadic_deduction_guide.cpp:31:23:   required from here
variadic_deduction_guide.cpp:19:45: error: no matching function for call to 'std::tuple<>::tuple(int&)'
     custom_tuple(Args... args): data(args...) {}

这是正常的还是编译器错误?

共有1个答案

许典
2023-03-14

这是 gcc 错误 80871。下面解释了为什么代码格式正确(clang在确定t2custom_tuple

弄清楚如何处理的过程

custom_tuple t2(42);

基本上涉及合成一堆函数并对其执行过载解析。相关的候选者是来自一个构造函数和推导指南的合成函数:

template <class... T, class... Args>
custom_tuple<T...> foo(Args... );     // the constructor

template <class... Args>
custom_tuple<Args...> foo(Args... );  // the deduction guide

从这一点上讲,这是一个根据[temp.arg.explicit]/3对“拖尾参数包”的解释选择自己的冒险:

未以其他方式推导的尾随模板参数包将被推导为模板参数的空序列。如果可以推导所有模板参数,则可以将它们全部省略;在这种情况下,空模板参数列表

< code>T...没有尾随

这个案子很简单。我们只有一个可行的候选者(因为< code>T...不可演绎)-演绎指南候选。我们推导出<代码>参数...作为< code>{int},所以我们以< code>custom_tuple结束

T...正在尾随

gcc和clang实际上都认为演绎对于构造函数来说是成功的。所以我们进入了[over.match.best]的决胜局:

给定这些定义,可行函数< code>F1被定义为比另一个可行函数< code>F2更好的函数,如果[...]

  • F1F2是函数模板的专门化,根据[temp.func.order]中描述的偏序规则,F1的函数模板比F2的模板更专业化,如果不是这样,则为
  • F1是根据扣减指南生成的([over.match.class.decrete]),而F2,如果不是,则为[…]

出于分排序的目的,相关类型只是那些与函数参数相对应的类型,并且我们可以忽略未使用的模板参数,因此两个函数模板都不被视为比另一个更专业。

这让我们更喜欢演绎指南,这是整个过程中最简单的一步。我们将<code>Args…,因此我们最终得到<code>custom_tuple

不管怎样,< code>custom_tuple

 类似资料:
  • 请考虑以下定义和演绎指南: 如果我尝试使用显式模板参数实例化 ,代码将正确编译: 如果我试图通过演绎指南实例化< code>foo... > G7产生编译器错误: clang 5 爆炸: wandbox上的实例 虽然clang肯定被窃听了(报告为问题#32673),但g拒绝我的代码是正确的吗?我的代码格式错误吗?

  • 假设有一个模板函数 接受任意数量的参数。给定最后一个参数始终是 ,我如何实现下面显示的 模板,以便 包含此 的参数? 例如,如果像这样调用,应该是: 我的第一个想法是: 但这不会编译: 问题一: 为什么这不能编译?为什么模板参数演绎失败? 最终,我想出了这个解决方案: 这里,是,即中的最后一种类型。然后,的临时值被传递到,其中。这行得通,但在我看来很难看。 问题二: 我想知道如果没有两个函数和的临

  • 最近一直在玩C的类型演绎。在这样做的时候,我遇到了一些奇怪的事情。当我运行这段代码时: 它打印出这个: 因此,很明显存在缓冲区溢出,因此为 。但我不明白的是,为什么auto没有适应像的东西,为什么它(4字节)?有没有办法解决这个问题?

  • 是否可以创建的可变版本,该版本可以使用任意数量的参数? 更新:在的模板版本中,是否允许以下指南语法?

  • 在传递函数时,我遇到了这个模板演绎/替换问题。有人可以帮忙吗,我非常感谢: 以下是编译代码时的错误: 示例.cpp:在 'bool Region::setAllValues(D) 的实例化中

  • Section Contents 入门 模板 + 数据模型 = 输出 数据模型一览 模板一览 数值,类型 基本内容 类型 模板 总体结构 指令 表达式 插值 其它 自定义指令 在模板中定义变量 命名空间 空白处理 替换(方括号)语法