我有一段C ++代码如下:
template <typename ...A>
struct CastAll{
template <typename ...B>
void cast_all(void(*fun)(B...), A...as){
//...
}
};
我想要做的是以这样一种方式实现cast_all:它将每个参数动态转换为其在B中的相应类型,然后使用“已铸造”参数调用给定函数的乐趣。
例如,在:
struct A{};
struct B : public A{};
void foo(B *b1, B *b2){
//... does something with b1 and b2
}
int main(){
A *a1 = new B();
A *a2 = new B();
CastAll<B*, B*> cast; //used to cast each A* to B*
cast.cast_all<B*, B*>(foo, a1, a2);
}
cast_all应扩展为:foo(dynamic_cast(a1),dynamic_cast(a2));
我查看了很多关于可变参数模板的文章。然而,几个小时后,我仍然无法弄明白。
有什么想法吗?
答案 0 :(得分:10)
简单地
template <typename ...A>
struct CastAll{
template <typename ...B>
void cast_all(void(*fun)(B...), A...as){
fun(dynamic_cast<B>(as)...);
}
};
应该有效,而且它与我的GCC副本有关。但是,您需要对示例代码进行一些更改:A
应该是多态的(这将使B
多态),以便dynamic_cast
成为可能(我添加了一个虚拟的默认析构函数)在我的示例代码中习惯);你可能打算用CastAll
作为:
CastAll<A*, A*> cast;
cast.cast_all(foo, &a1, &a2);
也就是说,您传递给cast_all
的参数是指向A
的指针,然后向下传递到正文内的B
。此外,一些模板参数推导出 1 。
这是有效的,因为您可以在一个包扩展中使用多个参数包(此处为A
和B
)(此处为dynamic_cast
),前提是它们具有相同的参数包尺寸;否则,由于SFINAE,这是一个无声的错误。来自n3290,14.5.3 / 5 Variadic模板[temp.variadic]:
- [...]包扩展的模式应命名一个或多个参数包 没有通过嵌套包扩展扩展;这样的参数包 在模式中称为未扩展参数包。全部 通过包扩展扩展的参数包应具有相同的参数包 指定的参数数量。 [...]
醇>
1 :我无法找到关于是否允许扣除的明确参考;如果我将CastAll
转换为多态仿函数,GCC甚至能够推导出两个包。如果这是强制行为,我有点怀疑,但至少你似乎知道如何指定非演绎的论证。
答案 1 :(得分:0)
[编辑]从头开始重写。这样的事情应该是可能的,但我没有一个编译器的acecss,它允许变量模板函数不成为结束,因为不再需要它。如果你没有传递至少一个参数,这确实会失败,但我没有看到这是一个问题。
template<typename...BL>
struct Recast {
template <typename B, typename ...BR>
struct Inner {
template <typename A, typename ...AR>
static void cast_all(void(*fun)(BL...,B,BR...), BL... al, A a, AR... ar) {
Recast<BL..., B>::template Inner<BR...>::cast_all<AR...>(fun, al..., dynamic_cast<B>(a), ar..);
}
};
template <typename B>
struct Inner<B> {
template <typename A>
static void cast_all(void(*fun)(BL...,B), BL... al, A a) {
fun(al..., dynamic_cast<B>(a));
}
};
};
template <typename ...BR> //note I switched these
struct CastAll{
template <typename ...AR> //note I switched these
static void cast_all(void(*fun)(BR...), AR...ar){
Recast<>::template Inner<BR...>::cast_all(fun, ar...);
}
};
struct A{};
struct B : public A{};
void foo(B *b1, B *b2){
//... does something with b1 and b2
}
int main(){
A *a1 = new B();
A *a2 = new B();
CastAll<B*, B*>::cast_all(foo, a1, a2);
}
我承认,根据ideone.com的报道,我仍然无法弄清楚
prog.cpp:在静态成员函数中'static void Recast :: Inner :: cast_all(void(*)(BL ...,B,BR ...),BL ...,A,AR .. )“:
prog.cpp:7:39:错误:在'...'标记之前预期的primary-expression
prog.cpp:7:39:错误:预期';'在'...'令牌之前