给定重载函数 f1
:
void f1(int);
int f1(char);
还有一个类模板X
带成员(member)模板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::f
当 Y<int, void>
时到类似下面的内容被实例化:
template<class... U>
void f(int(*p0)(U0), void(*p1)(U1));
哪里U0
和 U1
表示参数包的前 2 个元素 U
.
但似乎编译器(g++/clang)拒绝这样做并留下整个p
未用完。
它在标准中的哪个位置指定了这种行为?它可能是标准缺陷还是需要改进?
最佳答案
我已经提取了另一个有效的代码片段,虽然仍然不能满足您的需求,但可能会引导您做一些事情:
void f1(int)
{
}
int f1(char)
{
return 0;
}
template <class Out, class In>
struct UniFunction
{
typedef Out fn(In);
typedef fn* ptr;
};
template<class... T>
struct Y
{
//template<class... U>
//static void f(T(*...p)(U)...);
template <class... U>
struct YY
{
static void f(typename UniFunction<T, U>::ptr...)
{
}
};
};
int main( int argc, char** argv )
{
Y<int>::YY<char>::f(f1);
return 0;
}
这UniFunction
只是为了清楚起见,也许表明参数包的双重并行扩展并非不可能,只是有一个小问题。
我认为如果您另外提供一个“模板函数”(带有 typedef 的结构模板),它将从函数指针中提取(使用 type_traits
或其他东西)参数类型和返回类型,您仍然可以强制执行参数类型推导。这样,您应该能够提供 Y::f
只有一个模板参数(有点 X...
)的函数,从 X
中提取参数类型作为函数指针,然后将其显式传递给 YY
模板,如此处所示。
关于c++ - 外参数包可以用内参数包展开推导吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39283666/