首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有两个参数包的函数模板重载解析

带有两个参数包的函数模板重载解析
EN

Stack Overflow用户
提问于 2018-11-18 05:27:12
回答 1查看 519关注 0票数 12

考虑以下代码:

代码语言:javascript
运行
复制
#include<iostream>

template<class..., class... T>
int f(T...) { return 1; }

template<class... T>
int f(T...) { return 2; }

int main()
{
    std::cout << f(1);
}

它在gcc 8.2上编译和打印1,但由于调用f(1)不明确而无法在clang 7上编译。

如果调用被f()替换,那么两个编译器都无法编译,声称调用是不明确的。

如果将参数packs class... T替换为简单参数class T ( T...替换为T),则这两个编译器也都声称存在歧义。

在第一个例子中,哪一个编译器是标准的?我想这可以归结为函数模板的特定偏序规则,还是用这种方式使用双参数包已经不合适了?

编辑:

我的理解是,双包本身并不是格式错误的,因为在我的阅读中,temp.param 17.1/15似乎明确允许这样做,如果第二个包可以从函数参数中还原,这似乎是因为T...函数参数包的缘故。

还可以显式地指定第一个参数包的参数,但不是第二个参数包,因此并不总是这样(在模板参数推导之后)至少一个参数包是空的。我不知道这是否使程序的格式不正确,因为我不知道如何阅读例如temp.res 17.7/8.3在这种情况下。

gcc和clang对双参数包本身似乎都很好,例如,当第二个函数模板重载被删除时,两个编译器都打印1。但这可能是一个畸形的病例,不需要诊断。

此外,我假设使用类模板参数演绎,变量类模板可以定义一个可变构造函数模板,这将意味着一个类似于我的双参数包示例的构造函数候选,并且据我理解,相同的重载解析和模板参数演绎都发生在该上下文中。这个问题是由另一个有这样一个设置的问题引起的:变量类模板演绎失败与gcc 8.2,编译与clang和msvc (也请参阅有关该问题的讨论:带可变模板构造函数的演绎指南和可变类模板.不匹配的参数包长度 )

现在我也找到了演绎指南和可变模板问题的答案,我认为这意味着gcc是错的,这个呼吁应该被认为是模棱两可的,但我想让它验证一下,这同样适用于这里。我也欢迎更详细的推理,因为函数模板偏序规则在我看来非常不清楚。

EN

Stack Overflow用户

回答已采纳

发布于 2018-11-18 16:28:52

这里有两个问题。

首先,[temp.deduct.partial]/12 (我也引用了这个例子,因为它与您的相似)说:

在大多数情况下,如果不是所有模板参数都有值,扣减就会失败,但出于偏序的目的,模板参数可能仍然没有值,只要它不用于用于偏序的类型中。 注:非推导上下文中使用的模板参数被认为是使用的.- end注意事项 

用于偏序的类型是T... (根据[temp.deduct.partial]/3 )

用于确定排序的类型取决于执行偏序的上下文:

  • 在函数调用的上下文中,所使用的类型是函数调用具有参数的函数参数类型。
  • ..。

因此,第一个未命名的模板参数pack class...不影响偏序的结果。由于这两个函数模板没有其他不同之处,所以两者都不是比另一个更专门化,从而导致了一个模糊的调用。

可能与GCC的bug 49505有关。

第二,即使第二个函数模板不存在,调用仍然应该是不正确的。根据[temp.arg.explicit]/3的说法:

..。未导出的尾随模板参数包将被推导为模板参数的空序列.

只能将尾随模板参数包推断为空包,而第一个未命名的模板参数包class...不是尾随模板参数包。

GCC (bug 69623)和Clang (bug 26435)都有这个问题的缺陷。

票数 5
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53358165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档