函数模板实例化时省略模板类型参数是否合法?规则及标准变化
关于C++函数模板调用中省略模板类型参数的合法性问题
先来看你给出的可变参数模板实现代码:
template<int index, typename T> void foo_impl(T value) { // Do something with index/value } template<int index, typename T, typename... Rest> void foo_impl(T value, Rest... values) { // Do something with index/value // Recursively handle remaining arguments foo_impl<index + 1>(values...); } template<typename... T> void foo(T... args) { foo_impl<1>(args...); } int main() { foo("test", 42); }
针对你的问题,逐一解答如下:
1. 这种省略模板类型参数的写法是否合法?
完全合法。你在调用foo_impl时只显式指定了非类型模板参数index,省略了后面的类型参数T和Rest...,这是标准允许的写法,编译器可以通过函数实参自动推导出这些省略的类型参数。
2. 具体规则是什么?
C++标准允许在调用函数模板时,混合使用显式指定模板参数和实参推导,核心规则有两点:
- 你必须显式指定模板参数列表中连续的前缀部分,剩下的参数必须能通过函数实参推导出来。在你的代码里,
foo_impl的模板参数顺序是<int index, typename T, typename... Rest>,你显式指定了第一个参数index,后面的T和Rest...可以从传入的values...实参中推导,符合这个要求。 - 被推导的模板参数必须是可以通过函数实参确定的类型/值,这里的
T对应第一个剩余实参的类型,Rest...对应剩下的所有实参的类型包,完全可以被编译器推导出来。
3. 这些规则在不同C++标准间是否有变化?
从C11引入可变参数模板开始,这种混合显式指定+推导的规则就已经确立了。后续的C14、C17、C20乃至C23都没有修改这个核心规则——唯一的变化是后续标准对模板实参推导的细节做了一些补充(比如C17的类模板实参推导,但这和你这个函数模板的场景无关),但你代码里的写法在所有支持可变参数模板的C++标准中都是合法的。
简单来说,只要编译器支持C++11及以上标准,这段代码的写法就没问题,这也是为什么Clang、GCC、MSVC都能编译通过的原因。
内容的提问来源于stack exchange,提问作者IInspectable
相关产品推荐
相关产品推荐

