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

使用显式模板参数列表和[temp.arg.explicit]/3的函数调用的演绎失败

益明朗
2023-03-14

C 17标准(最终草案)的[temp.arg.explicit]/3说明了使用显式指定的模板参数列表推导函数模板参数:

在扣除完成且失败的情况下,或[...],如果指定了模板参数列表,并且它与任何默认模板参数一起标识了单个函数模板专门化,则template-id是函数模板专门化的左值。

这如何应用于参数包?

认为

template<typename...>
struct S {
    S(int) {}
};

template<typename... A>
void f(S<A...>) {}

int main() {
    f<int>(0);
}

这可以在MSVC上编译,但不能在GCC和Clang上编译,请参见godbolt。这也是我的直觉,它应该失败,因为演绎将失败,但上面的引语似乎暗示,即使演绎失败,因为<code>f

我对这句话的理解有什么错误,或者MSVC真的正确吗?

请注意,如果我们试图调用< code>f

共有3个答案

向实
2023-03-14

有一个开放的核心语言问题(问题2055:显式指定的非推导参数包)与这种情况密切相关。

根据我对这个问题中隐含说明的理解,其意图是编译器应该像MSVC一样运行,但标准据说不够清晰。

欧阳智志
2023-03-14

这无关紧要。没有“没有重载解析”的函数调用。CWG2092明确了这一点。

[temp.over]/1控制(为了可读性而分开;重点是我的):

当写入对函数或函数模板名称的调用时(显式地或隐式地使用运算符表示法),对每个函数模板执行模板参数推导([temp.decrete])和任何显式模板参数([temm.arg])的检查,以找到可与该函数模板一起使用的模板参数值(如果有),从而实例化可与调用参数一起调用的函数模板专用化。

对于每个函数模板,如果参数演绎和检查成功,则模板参数(推断和/或显式)用于合成单个函数模板专用化的声明,该专用化将添加到要用于重载解析的候选函数集中。

如果对于给定的函数模板,参数推导失败或合成的函数模板特化格式错误,则不会将此类函数添加到该模板的候选函数集中。完整的候选函数集包括所有合成的声明和所有同名的非模板重载函数。合成的声明在重载解析的其余部分中被视为与任何其他函数一样,除非在[over.match.best]中明确指出。

王辉
2023-03-14

与这个问题相关的还有[temp.arg.explicit]/6,它告诉我们函数参数的隐式转换(如您在上面所希望的)是

如果参数类型不包含参与模板参数推断的模板参数。[ 注意:如果显式指定了模板参数,则不参与模板参数推断。[...]]

所以,现在的问题是A...是否参与模板参数推导。(在这一点上,我想注意到,如果我们用一个模板参数替换参数包,OPs代码也会在gcc/clang下编译,因为它应该是显式指定的)。

有人可能会说< code>A...是显式指定的,因此不参与推导。但我认为其中一个是错误的。[temp.arg.explicit]/9告诉我们,演绎可以扩展显式指定的模板参数列表。因此,< code>f

换句话说,f

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

  • 这些代码如下: 使用G++4.8.2错误信息编译:

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

  • 这是在参数是重载函数时重载解析如何工作中提到的更复杂的问题? 下面的代码编译起来没有任何问题: 模板参数推导似乎不是一项具有挑战性的任务-只有一个函数接受两个参数。但是,取消注释的模板重载(仍然只有一个参数)会无缘无故地破坏编译。gcc 5. x/6. x和clang 3.9的编译都失败了。 它可以用重载解析/模板参数推导规则来解释,还是应该在这些编译器中被限定为缺陷?

  • 如果我没有理解错的话,类模板定义了一个函数,所以当我调用时,编译器有可能进行隐式强制转换,但是在函数模板的情况下,此时没有函数定义,所以隐式强制转换不会发生。 但我不明白为什么编译器不能创建函数定义,然后应用隐式强制转换? 错误是: 在函数“int main()”中:    25:24:错误:调用“test2::add(void(&)(int))”没有匹配函数    25:24:注:候选人是:  

  • 考虑以下示例: 我的GCC 9.2.0无法编译并出现以下错误: 但是,工作正常。为什么会这样?如何使用显式模板参数调用foo?