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

将可变参数模板与 C 样式可变参数函数混合时的模板参数推导

吴安和
2023-03-14

受这个答案的启发,我生成了这段代码,其输出取决于编译器:

template <typename... Args>
constexpr auto foo(Args&& ...args, ...) noexcept {
    return sizeof...(args);
}

constexpr auto bar() noexcept {
    return (&foo<int>)(1, 2);
}

如果使用 GCC 11 编译,则酒吧调用 foo

这是我在神闩上的沙盒:https://godbolt.org/z/MedvvbzqG。

哪个输出是正确的?

编辑:

如果我使用< code>return foo,错误行为仍然存在

constexpr auto bar() noexcept {
    return foo<int>(1, 2);
}

沙盒更新:https://godbolt.org/z/Wj757sc7b.


共有1个答案

龙浩博
2023-03-14

编辑:问题编辑后,它现在由两个正交的子问题组成,我已经分别处理了这两个问题。

是的。参数包确实出现在参数声明列表的末尾,这是它是否是非推导的标准。这实际上在CWG第1569期中得到了澄清。我们可以通过观察所有编译器都同意这很好来说服自己:

template <typename... Args>
constexpr auto foo(Args&& ...args, ...) noexcept {
    return sizeof...(args);
}

static_assert(2 == foo(1, 2), "always true");

只有当我们把傻瓜换成傻瓜时

答案是肯定的,正如CWG公开问题1038中所讨论的那样:

一个相关的问题涉及这样的例子

struct S {
    static void g(int*) {}
    static void g(long) {}
} s;

void foo() {
    (&s.g)(0L);
}

因为地址出现在调用上下文中,而不是在12.3[over.over]第1段中提到的上下文中,所以foo中的调用表达式可能格式错误。将此与类似示例进行对比

void g1(int*) {}
void g1(long) {}

void foo1() {
    (&g1)(0L);
} 

这个调用可能格式良好,因为12.2.2.2[over.match.call]适用于“一组重载函数的地址”

正如注释所述,在第704期之前,我们有一个非常明确的部分:

第四种情况来自形式的后缀表达式

这一措辞最终被删除的原因并不是因为它有缺陷,而是因为整个章节措词不当。新的措辞仍然明确表示重载解析适用于重载集的地址(这就是我们这里所说的):

如果后缀表达式表示一组重载函数和/或函数模板的地址,则如上所述使用该集应用重载解析。

 类似资料:
  • 在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty

  • 我已经编写了一个具有递归评估的可变参数模板函数。对于最后一个参数,我在没有可变参数包的情况下实现了专业化,并且一切正常。 现在我想把可变函数参数转换成模板参数。 这是我的尝试: gcc和clang报告了一个模糊的过载,并且无法使用空参数包在“专业化”和“可变参数”之间做出决定。 我尝试删除特化并检查可变参数模板中的包大小,但是如果没有特化,编译器就无法推断出参数“p”。

  • 以下是我的代码:< br > 一开始我只是重载了函数,发现有很多类似的代码。所以我正在考虑使用可变参数模板来获得更好的设计。(如果两个重载函数相似,如何做出更好的设计) 但是我不知道为什么会有错误:< br > main.cpp:27: 8:错误:没有匹配函数调用'getChar'ch=getChar(1, std::forward(str)...); 主要的cpp:37:2:注意:在函数模板专门

  • 要解决的问题: 怎么创建一个拥有1个、2个或者更多的初始化器的类? 怎么避免创建一个实例而只拷贝部分的结果? 怎么创建一个元组? 最后的问题是关键所在:考虑一下元组!如果你能创建并且访问一般的元组,那么剩下的问题也将迎刃而解。 这里有一个例子(摘自“可变参数模板简述(A brief introduction to Variadic templates)”(参见参考)),要构建一个广义的、类型安全的

  • 当我编译时,我得到了这些错误:

  • 我希望打印函数根据“值”的类型来做不同的事情。