【发布时间】:2017-01-10 01:18:24
【问题描述】:
给定重载函数f1:
void f1(int);
int f1(char);
还有一个类模板X和成员模板f:
template<class T>
struct X
{
template<class U>
static void f(T(*p)(U));
};
编译器能够从部分函数类型解析f1:
X<int>::f(f1); // T = int (specified), U = char (deduced)
X<void>::f(f1); // T = void (specified), U = int (deduced)
然而,一个可变参数类模板Y 两边都有参数包:
template<class... T>
struct Y
{
template<class... U>
static void f(T(*...p)(U));
};
没有做同样的事情:
Y<int>::f(f1); // error
Y<void>::f(f1); // error
Y<int, void>::f(f1, f1); // error
注意,参数包只在一侧也可以:
template<class... T>
struct Z1
{
template<class U>
static void f(T(*...p)(U));
};
template<class T>
struct Z2
{
template<class... U>
static void f(T(*...p)(U));
};
Z1<int>::f(f1); // ok
Z2<void>::f(f1); // ok
这显示了一个问题:外部参数包T 无法扩展,而内部参数包U 仍然依赖。
我想当 Y<int, void> 被实例化时,编译器可以将 Y::f 扩展为如下所示:
template<class... U>
void f(int(*p0)(U0), void(*p1)(U1));
其中U0 和U1 表示参数包U 的前两个元素。
但编译器(g++/clang)似乎拒绝这样做,并留下整个 p 未使用。
它在标准中的什么地方指定了这种行为?可能是标准缺陷还是需要改进的地方?
【问题讨论】:
-
我认为问题在于替换了外包装的明确指定的参数。由于那时内包装仍然是空的,因此在扩展过程中会出现尺寸不匹配的情况。但是我不记得这里的规则。
-
我认为这里适用的规则是“通过包扩展扩展的所有参数包都应指定相同数量的参数。”
标签: c++ templates c++11 language-lawyer variadic-templates