繁体   English   中英

当其中一个包含包时,MSVC 无法消除功能模板之间的歧义

[英]MSVC not able to disambiguate between function templates when one of them contains a pack

最近我报告了一个涉及函数参数包的msvc 错误 同样,这里证明 msvc 实际上是符合标准的。

然后,当我将示例修改为如下所示时,我注意到修改后的代码也无法在 msvc 中编译,但可以在 clang 和 gcc 中编译。 代码如下: Demo链接

template<typename T> struct C{};

template<typename T> void f(C<T>)
{

}
template<typename... T> void f(C<T...>)
{

}
int main()
{
    f(C<int>{}); //Should this call succeed? 
}

请注意,在上面的示例中,我们将C<T...>作为函数参数,而不仅仅是T... 现在,在上面显示的示例中,我不能 100% 确定这是 msvc 问题还是标准不允许该程序。

所以我的问题是,上面显示的代码示例格式是否正确。 也就是说,应该调用f(C<int>{}); 成功选择第一个重载void f(C<T>)而不是void f(C<T...>)

换句话说,哪个编译器就在这里。

所以我的问题是,上面显示的代码示例格式是否正确。

代码格式良好,因为通过部分排序规则,具有非可变模板参数的函数模板重载比具有可变参数模板参数的重载更专业。

MSVC 拒绝它是不正确的。


[temp.func.order]/1/4告诉我们需要转向偏序

/1如果函数模板被重载,则函数模板特化的使用可能不明确 [...]。 在以下上下文中使用重载函数模板声明的部分排序来选择函数模板特化所引用的函数模板:

  • /1.1 在重载决议期间调用函数模板特化 ([over.match.best]);
  • [...]

/2部分排序通过依次转换每个模板(参见下一段)并使用函数类型执行模板参数推导来选择两个函数模板中的哪一个比另一个更专业。 [...] 如果是这样,更专业的模板是部分排序过程选择的模板。 如果两个推导都成功,则部分排序选择更受约束的模板(如果存在),如下所示。

/3要生成转换后的模板,对于每个类型、非类型或模板模板参数(包括其模板参数包),分别合成一个唯一的类型、值或类模板,并将其替换为函数中该参数的每次出现模板的类型。

/4使用转换后的函数模板的函数类型,对另一个模板执行类型推导,如 [temp.deduct.partial] 中所述。

[temp.deduct.partial]

/2两组类型用于确定偏序。 对于涉及的每个模板,都有原始函数类型和转换后的函数类型。 推演过程使用转换后的类型作为参数模板,将另一个模板的原始类型作为参数模板。 [...]

/4上面从参数模板中指定的每个类型和来自参数模板的相应类型都用作 P 和 A 的类型。

/8使用结果类型 P 和 A,然后按照 [temp.deduct.type] 中的描述进行扣除。 [...]如果给定类型的推导成功,则参数模板中的类型被认为至少与参数模板中的类型一样特化。

对于原始单函数参数函数模板,产生以下 P/A 对:

    P         A
    --------  ----------
#1: C<T>      C<Unique1...>
#2: C<T...>   C<Unique2>

通常,当不在偏序的上下文中时,这两个对的演绎都会成功。 但是, [temp.deduct.type]/9有一个特殊情况,当扣除作为部分排序的一部分执行时:

/9 [...] 在部分排序期间,如果 Ai 最初是一个包扩展

  • /9.2 否则,如果 Pi 不是包展开,则模板参数推导失败。

该子句意味着扣除上面的#1C<T> from C<Unique1...> )失败,而#2C<T...> from C<Unique2> )成功并且C<Unique2>被认为是至少与C<T...>一样专业。 根据[temp.deduct.partial]/10 ,非可变参数函数模板重载因此至少与可变参数模板函数重载一样专业化,并且在没有反之亦然关系的情况下,专业化:

/10函数模板 F 至少与函数模板 G 一样特化,如果对于用于确定排序的每对类型,来自 F 的类型至少与来自 G 的类型一样特化。如果 F 比 G 更特化至少和 G 一样特化,而 G 至少不像 F 那样特化。

这将我们带回到[temp.func.order]/2并通过偏序选择更专业的函数模板:

/2 [...] 推演过程决定了其中一个模板是否比另一个更专业。 如果是这样,更专业的模板是部分排序过程选择的模板。

[over.match.best]/2.5也涵盖了这一点

/2鉴于这些定义,如果对于所有参数 i,ICSi(F1) 不是比 ICSi(F2) 更差的转换序列,则可行函数 F1 被定义为比另一个可行函数 F2 更好的函数,然后

  • [...]
  • /2.5 F1 和 F2 是函数模板特化,根据 [temp.func.order] 中描述的偏序规则,F1 的函数模板比​​ F2 的模板更特化,否则,[... ]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM