【问题标题】:What is the normative rule in the current draft rules that a template parameter pack which does not participate in deduction is deduced to empty现行规则草案中将不参与推演的模板参数包推演为空的规范规则是什么
【发布时间】:2021-06-20 17:35:23
【问题描述】:
template<typename ...T, typename U>
void fun(U){}
int main(){
   fun(0);
}

GCC 和 Clang 都接受这个 sn-p 代码。模板形参包T在函数调用上下文中不参与模板实参推演,规则如下:
[temp.deduct.call]

模板参数推导是通过比较每个函数模板参数类型(称为P),其中包含模板参数参与模板参数推导的类型调用的相应参数(称为 A),如下所述。

T 包含在任何函数模板参数中。如果没有其他特殊规则,则根据:
[temp.deduct.type#2]

如果任何模板参数既没有推导也没有明确指定,则模板参数推导失败。

但是,这种情况是由当前标准中的以下规则来裁定的,即: [temp.arg.explicit#4]

一个尾随模板参数包 ([temp.variadic])不会以其他方式推导推导为模板参数的空序列

因此,可以认为上面的情况可以成功地推导出包T 带有一组空的模板参数。

但是,temp.arg.explicit#4 中的特殊规则已更改为当前草案中的注释

[temp.arg.explicit#note-1]

[注 1:未以其他方式推导的尾随模板参数包 ([temp.variadic]) 将推导为模板参数的空序列。 ——尾注]

所以,我想知道当前草案中是否有任何替代的规范性规则规定包T 没有以其他方式推断将被推断为一组空的模板参数?

【问题讨论】:

    标签: c++ templates language-lawyer


    【解决方案1】:

    [temp.arg.explicit]/4 之前的规范部分

    [...] 没有以其他方式推导的尾随模板参数包 ([temp.variadic]) 将被推导为模板参数的空序列。 [...]

    作为P1787R6 的一部分被制成非规范性注释。

    正如您所指出的,按照[temp.deduct.type]/2 [emphasis 我的]:

    类型推导对每个 P/A 对 [...] 独立完成,如果 任何模板参数 既没有推导也没有明确指定,则模板参数推导失败。

    [temp.arg.general] 描述了作为模板参数包的模板参数可能对应于零个模板参数

    [...] 当模板声明的参数为模板参数包时,会对应或多个template-arguments

    [temp.variadic]/1 明确提到模板参数包可以接受零参数:

    模板参数包是接受零个或多个模板参数的模板参数。

    接下来是一个非规范性示例,该示例是在参数包模板参数上模板化的实体的空参数列表:

    template<class ... Types> struct Tuple { };
    Tuple<> t0;  // Types contains no arguments
    

    现在,返回[temp.arg.explicit]/4

    如果所有的模板参数都可以推导出来,可以全部省略;在这种情况下,空模板参数列表&lt;&gt; 本身也可以省略。

    意思是上面的Tuple例子同样可以省略空参数列表

    Tuple t0;  // Also OK: Types contains no arguments
    

    但关键在于,根据上面的 [temp.arg.general],模板参数列表可能对应于零个参数,在这种情况下,不需要推导模板参数。

    如果你看看你自己的例子:

    template<typename ...T, typename U>
    void fun(U){}
    int main(){
       fun(0);  // #1
    }
    

    你同样可以调用#1

    fun<>(0);  // argument list for parameter pack is empty
               // -> no argument (beyond that for `U`) to deduce
    

    强调与模板参数U 对应的可推导参数可以从显式模板参数中省略,而其余模板参数没有;即作为模板形参包的模板形参的实参列表为空,因此没有剩余的模板实参需要推导。

    这样

    没有以其他方式推导的尾随模板参数包 ([temp.variadic]) 将被推导为模板参数的空序列。

    是非规范性/冗余的,解释了为什么它被包装成一个[Note - [...] - end note]

    【讨论】:

    • 我并不是说这是错误的,但我认为讨论以下情况会有所帮助(1)模板参数包未用于函数参数列表中的可推导上下文中,以及(2)模板形参包用于函数形参列表的可推导上下文中,调用表达式中有零个对应的函数实参。显然两者都满足 [temp.arg.explicit]/4 “如果可以推导出所有模板参数”?
    • @aschepler (1) 将完全被上面的答案覆盖,如果我没记错的话,而 (2) 被上面的 + [temp.variadic]/2[temp.variadic]/8 覆盖,它涵盖了 ( /2) 函数参数包 可以接受零个参数和 (/8) 对封闭结构的影响(比如函数模板,以及它所指的特化)对于函数参数包的情况为空(“N 为零”)。
    • @dfrib 我无法理解的是,“对应零个或多个模板参数”的意思是,如果一个不参与推导的模板参数包被推导为空。例如Tuple&lt;&gt;,在这种情况下包确实对应于零参数,换句话说,Pi 是从 Ai 推导出来的,它是空的。在我的示例中,该包根本没有出现在任何P 中。在我看来,推论是一个比较 P 和 A 的动作。
    • @jackX 我认为从 [temp.variadic]/1、/2 和 /8 可以清楚地看出,如果没有提供任何参数,模板参数列表将为空显式地通过模板参数列表或通过相关函数参数包的扩展和推导。我这些都不适用,作为参数包的模板参数对应于零个模板参数,因此没有模板参数(来自包)可以应用推导。我想争辩说,现在非规范性注释中使用的“演绎”有点不幸:没有论证演绎......
    • ...这里,只是可变参数模板的规则,这样就不会有模板参数与模板参数包相关联(并且没有 P/A 推论)。跨度>
    猜你喜欢
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 2014-04-17
    • 2017-02-08
    • 1970-01-01
    • 2023-01-14
    • 1970-01-01
    • 2017-01-12
    相关资源
    最近更新 更多