c++ - 用于转换多个参数的模板函数

标签 c++ c++11 templates variadic-templates template-meta-programming

我正在尝试编写一个模板函数,该函数将根据其模板参数执行一组 dynamic_casts()。我有以下内容来说明:

class FooData
{
public:
    virtual ~FooData() {};
};
class DerivedFooData: public FooData{};
class Other: public FooData{};

void bar(DerivedFooData* d1, DerivedFooData* d2) {}
void bar(DerivedFooData* d1, Other*, DerivedFooData* d2, Other*, Other*) {}


int main()
{
    DerivedFooData d1,d2;
    std::vector<FooData*> container1{&d1, &d2};
    std::vector<FooData*> container2{&d1, &d2};

    // I want bar to be called with container1[0] cast to DerivedFooData and container2[1] cast to DerivedFooData 
    // the first two template params are each container size

    foo<1, 1, DerivedFooData, DerivedFooData>(container, container2);

    // I want bar to be called with
    // container1[0] cast to DerivedFooData
    // container1[1] cast to Other
    // container2[0] cast to DerivedFooData
    // container2[1] cast to Other
    // container2[2] cast to Other
    foo<2, 3, DerivedFooData, Other, DerivedFooData, Other, Other>(container, container2);
}

我可以手动创建其中一些:

template <int N, int M, typename U, typename V>
void foo(const std::vector<FooData*>& input, const std::vector<FooData*>& output) 
{
    bar(dynamic_cast<U*>(input[0]), dynamic_cast<V*>(output[0]));
}

template <int N, int M, typename U, typename V, typename W, typename X, typename Y>
void foo(const std::vector<FooData*>& input, const std::vector<FooData*>& output) 
{
    bar(dynamic_cast<U*>(input[0]), dynamic_cast<V*>(input[1]), dynamic_cast<W*>(output[0]), dynamic_cast<X*>(output[1]), dynamic_cast<Y*>(output[2]));
}

但我不知道如何以通用方式指定 NM 的所有组合。我假设可变参数模板会出现在某个地方,但我需要一些指导。

最佳答案

一点也不优雅(并且不确定确切的索引)但是......下面的东西(假设你可以使用 C++14)应该可以工作(如果我理解正确的话你想要什么)

template <std::size_t Dim1, typename ... Ts, std::size_t ... Is>
void foo_helper (std::index_sequence<Is...>, std::vector<FooData*> inV,
                 std::vector<FooData*> outV)
 { bar( dynamic_cast<Ts*>(Is < Dim1 ? inV[Is] : outV[Is-Dim1])... ); }

template <std::size_t Dim1, std::size_t Dim2, typename ... Ts>
void foo (std::vector<FooData*> inV, std::vector<FooData*> outV)
 { foo_helper<Dim1, Ts...>
      (std::make_index_sequence<Dim1+Dim2>{}, inV, outV); }

我知道 C++20 对您来说太新了,但是为了好玩,我将向您展示如何使用新的 C++20 lambda 模板功能来避免使用辅助函数

// from C++20: foo_helper() isn't needed anymore
template <std::size_t Dim1, std::size_t Dim2, typename ... Ts>
void foo (std::vector<FooData*> inV, std::vector<FooData*> outV)
 { [&]<std::size_t ... Is>(std::index_sequence<Is...>)
    { bar( dynamic_cast<Ts*>(Is < Dim1 ? inV[Is] : outV[Is-Dim1])... ); }
      (std::make_index_sequence<Dim1+Dim2>{}); }

下面是一个完整的编译C++14的例子

#include <vector>
#include <type_traits>


struct FooData { virtual ~FooData() {}; };
class DerivedFooData: public FooData { };
class Other         : public FooData { }; 

void bar (DerivedFooData*, DerivedFooData*) {}
void bar (DerivedFooData*, Other*, DerivedFooData*, Other*, Other*) {}

template <std::size_t Dim1, typename ... Ts, std::size_t ... Is>
void foo_helper (std::index_sequence<Is...>, std::vector<FooData*> inV,
                 std::vector<FooData*> outV)
 { bar( dynamic_cast<Ts*>(Is < Dim1 ? inV[Is] : outV[Is-Dim1])... ); }

template <std::size_t Dim1, std::size_t Dim2, typename ... Ts>
void foo (std::vector<FooData*> inV, std::vector<FooData*> outV)
 { foo_helper<Dim1, Ts...>
      (std::make_index_sequence<Dim1+Dim2>{}, inV, outV); }

int main ()
 {
   DerivedFooData d1, d2, d3;
   std::vector<FooData*> container1 {&d1, &d2};
   std::vector<FooData*> container2 {&d1, &d2, &d3};

   foo<1, 1, DerivedFooData, DerivedFooData>(container1, container2);

   foo<2, 3, DerivedFooData, Other, DerivedFooData, Other, Other>
      (container1, container2);
 }

关于c++ - 用于转换多个参数的模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57794926/

相关文章:

c++ - 将 rand_r 更改为 srand/rand

C++11:decltype((x)) 和 decltype((x+1)) 的类型不同?

c++ - 从模板参数中指定常量值

c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

没有模板参数的类的 C++ 专用构造函数(跳过尖括号)

c++ - 来自文件夹而不是 MSI 的 Windows 应用商店部署文件

c++ - 通过指向在另一个线程上执行的函数的指针传递堆栈分配的对象

c++ - 在后台 C++ 程序/bash 脚本中捕获 linux 命令的输出

c++ - 混合 libstdc++ 版本

c++ - is_lock_free 未在 gcc 4.7.2 的 std::atomic<T> 中定义?