变体模板和动态演员

时间:2011-09-07 21:48:28

标签: c++ templates c++11 dynamic-cast

我有一段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));

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

有什么想法吗?

2 个答案:

答案 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

这是有效的,因为您可以在一个包扩展中使用多个参数包(此处为AB)(此处为dynamic_cast),前提是它们具有相同的参数包尺寸;否则,由于SFINAE,这是一个无声的错误。来自n3290,14.5.3 / 5 Variadic模板[temp.variadic]:

  
      
  1. [...]包扩展的模式应命名一个或多个参数包   没有通过嵌套包扩展扩展;这样的参数包   在模式中称为未扩展参数包。全部   通过包扩展扩展的参数包应具有相同的参数包   指定的参数数量。 [...]
  2.   

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:错误:预期';'在'...'令牌之前