变体模板和动态演员

Fil*_*njo 7 c++ templates dynamic-cast c++11

我有一段C++代码如下:

template <typename ...A> 
struct CastAll{
  template <typename ...B>
  void cast_all(void(*fun)(B...), A...as){
    //...
  }
};
Run Code Online (Sandbox Code Playgroud)

我想要做的是以这样的方式实现cast_all:它将每个参数动态转换为B中的相应类型,然后使用"casted"参数调用给定的函数fun.

例如,在:

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);
}
Run Code Online (Sandbox Code Playgroud)

cast_all应扩展为:foo(dynamic_cast(a1),dynamic_cast(a2));

我看过很多关于可变参数模板的文章.然而,几个小时后,我仍然无法弄明白.

有任何想法吗?

Luc*_*ton 10

只是

template <typename ...A> 
struct CastAll{
    template <typename ...B>
    void cast_all(void(*fun)(B...), A...as){
        fun(dynamic_cast<B>(as)...);
    }
};
Run Code Online (Sandbox Code Playgroud)

应该工作,它与我的GCC副本一样.但是,您需要对示例代码进行一些更改:A应该是多态的(这将B依次变为多态),dynamic_cast以便可行(我在示例代码中添加了一个虚拟的,默认的析构函数); 你可能打算CastAll用作:

CastAll<A*, A*> cast;
cast.cast_all(foo, &a1, &a2);
Run Code Online (Sandbox Code Playgroud)

也就是说,你传递给它的参数cast_all是指向A它的指针然后向下转移B到体内.另外,推导出一些模板参数1.

这是有效的,因为你可以在一个包扩展(这里,)中使用几个参数包(这里A和),只要它们具有相同的大小; 否则,由于SFINAE,这是一个无声的错误.来自n3290,14.5.3/5 Variadic模板[temp.variadic]:Bdynamic_cast

  1. [...]包扩展的模式应命名一个或多个未通过嵌套包扩展扩展的参数包; 此类参数包在模式中称为未扩展参数包.通过包扩展扩展的所有参数包应具有相同数量的参数.[...]

1:我无法找到关于是否允许扣除的明确参考; 如果我CastAll变成一个多态仿函数,GCC甚至能够推断出两个包.如果这是强制行为,我有点怀疑,但至少你似乎知道如何指定非演绎的参数.