在c++中真的不可能跳过带有默认实参的模板形参吗?为什么语法不这么认为?
Is it really impossible to skip template parameters with default arguments in C++, why does syntax suggest otherwise?
我一直在试图找到一种方法来跳过不位于模板参数列表末尾的模板参数,在派生类中已在其基类中分配了默认值。
我对这个话题做了一些研究,也在SO上。虽然类似的问题已经在SO上讨论过了,但许多答案基本上表明它不起作用,这些问题与非常特殊的情况有关,比如这里的哈希映射情况。我还找到了"Potatoswatter"的答案,在我看来,这与跳过这样一个参数的不可能性相矛盾。在他的回答中,他声称这个声明是有效的:
template< class A, class B = int, class C >
class X;
假设模板形参不能被跳过(除非在实参列表的末尾),这样的声明根本没有意义。由于B被赋了一个默认值,但后面跟着没有默认值的C,在这种情况下,B总是必须显式赋值,使得int作为B的默认赋值完全无用。上面的X声明有意义的唯一场景是下列Y声明之一是有效的:
class Y : public X<double, , const std::string&> { ... }
class Y : public X<A = double, C = const std::string&> { ... }
那么,在派生专门化类时,真的不可能跳过不在模板形参列表末尾的模板形参吗?
如果这是不可能的,为什么会这样,为什么法律语法明显地表明不是这样(参见上面的类X示例)?
如果实际上不是不可能,如何跳过已被赋值为默认值的模板参数?
相关标准请参见"模板参数[temp.param]"(14.1)。
本质上,只有当它所应用的参数后面没有任何没有默认参数([temp.param]/11)的非包参数时,才可以使用默认参数。但是,您引用的语法在[temp.param]/10:
所描述的情况下可以在声明中使用。可使用的默认模板参数集是通过合并来自的默认参数获得的模板的所有先前声明都与默认函数实参相同(8.3.6)。(例子:
template<class T1, class T2 = int> class A; template<class T1 = int, class T2> class A;
等价于
template<class T1 = int, class T2 = int> class A;
- 结束示例]
这个词"类"是隐藏在你的问题,所以我想我会提到(即使这不是一个确切的答案),模板参数与默认值可以被"跳过",在调用函数模板。考虑以下代码:
template<class X, class Y = int, class Z>
void foo(X x, Y y, Z z) {
(void)x, (void)y, (void)z;
puts(__PRETTY_FUNCTION__);
}
int main()
{
foo(3.14, {}, 1.45f);
}
- 模板参数
X
推导为double
(默认值,如果有,将不使用)。 - 本次调用无法推导出模板参数
Y
,因此使用默认值int
。 - 模板参数
Z
推导为float
。
{}
在函数实参列表中的不可演绎性,在STL中为函数模板形参提供默认值的情况很多。参见std::exchange
或std::optional
的构造函数#8。
您可能期望c++ 17中的构造函数模板参数推导可以使用类似的技巧,但我的实验表明,这不是的情况。在类模板定义中,如果在列表中较早地放置template-parameter-with-default而不是template-parameter-without-default,编译器将生成诊断。
template<class X, class Y = int, class Z> // error!
struct Foo {};
- 使用mem_fun_ref if成员函数需要多个形参
- 通过类的模板形参特化成员模板结构
- 非类型引用形参/实参
- 哪个模板形参在boost::shared_ptr构造函数中使用一个原始指针
- 如何确保迭代器模板形参与模板类的模板形参具有相同的数据类型
- 如何在编译时通过模板形参默认值的名称/指针获取函数的类型
- c++:候选模板被忽略:模板形参显式指定的参数无效
- c++中作为形参的指针
- 哪种方法更适合为函数提供编译时间常数?函数实参与模板形参
- 为什么模板非类型形参指针和引用实参需要是全局的
- 为什么stable_sort函数中的ref形参需要const ?
- 在Bjarne的这个例子中,为什么可以将const限定对象传递给非const形参?
- 在c++中真的不可能跳过带有默认实参的模板形参吗?为什么语法不这么认为?
- 为什么c++ 11 CAS操作使用两个指针形参
- 为什么c++中通过引用传递的形参不需要解引用操作符
- 为什么标准不允许在模板形参列表中初始化依赖于常量的类型
- 为什么必须引用const来避免复制形参?
- 为什么这样调用构造函数时模板形参推导失败?
- 为什么在形参中使用initializer_list而不是vector ?
- 为什么不允许使用不同数量的模板形参的类/结构声明?