在可变参数函数中推导出不同参数包中的两个不同的已知类型变量

时间:2015-04-03 03:08:37

标签: c++ c++11 variadic-templates variadic-functions

我有以下代码:

template <typename... Type1, typename... Type2>
void foo(const Type1&&... t1, Type2&&... t2)
{
    int len = sizeof...(Type1);
    cout << len << endl;
    int len1 = sizeof...(Type2);
    cout << len1 << endl;
}

int main()
{
    foo(1, 2, 4.5, 5.5);

    return 0;
}

调用foo()会将Type1推送为空,将Type2推导为{int, int, double, double},而我希望将Type1推广为{int, int}并且Type2{double, double}。是否可以在不涉及std::tuple的情况下调用foo()函数,如上所述?

修改


为了更清楚地说明我想要实现的目标,这里有一个解释。我想创建一个函数,用户每次都可以在偶数对中传递任意数量的两种类型变量。让我们说foo(Type1 x, Type1 y, Type1 z, Type1 ..., Type2 XX, Type2 YY, Type2 ZZ, Type2 ...); Type1的变量总是const引用,而Type2的变量只是引用,所以函数将结束以下形式:foo(const Type1& x, const Type1& y, ..., Type2& XX, Type2& YY, ...)。在函数中,我将使用Type1变量应用一些计算,并通过Type2变量返回相应的结果。我知道任何容器结构的使用都会让我的生活变得更轻松,但不幸的是我无法解决这个问题。所以,虽然我不是一个经验丰富的人,我认为使用可变函数是可行的方法,我是对的吗?

2 个答案:

答案 0 :(得分:1)

不,编译器无法读懂你的想法。

您可以将一包类型分成两半:

template<class...>struct types{using type=types;};

template<class lhs, class rhs>struct cat;
template<class lhs, class rhs>using cat_t=typename cat<lhs,rhs>::type;

template<class...lhs, class...rhs>
struct cat<types<lhs...>,types<rhs...>>:
  types<lhs...,rhs...>
{};

template<class types, size_t n>
struct split {
private:
  using s0 = split<types,n/2>;
  using r0 = typename s0::lhs;
  using r1 = typename s0::rhs;
  using s1 = split<r1,n-n/2>;
  using r2 = typename s1::lhs;
public:
  using lhs = cat_t<r0,r2>;
  using rhs = typename s1::rhs;
};
template<class Types>
struct split<Types, 0>{
  using lhs=types<>;
  using rhs=Types;
};
template<class T0,class...Ts>
struct split<types<T0,Ts...>,1>{
  using lhs=types<T0>;
  using rhs=types<Ts...>;
};

然后我们使用它将foo参数拆分为两个包:

template<class types>
struct foo2_t;
template<class... T0s>
struct foo2_t<types<T0s...>>{
  template<class... T1s>
  void operator()(T0s&&... t0s, T1s&&... t1s) const {
    std::cout << sizeof...(T0s) << '\n';
    std::cout << sizeof...(T1s) << '\n';
  }
};

template <class... Ts>
void foo(Ts&&... ts) {
  using s = split< types<Ts...>, sizeof...(Ts)/2 >;
  foo2_t<typename s::lhs>{}( std::forward<Ts>(ts)... );
}

live example

如果你希望编译器做出不同的魔法(比如,对相同的类型,或者你想到的任何其他内容),可以使用不同的(但类似的)技术。

答案 1 :(得分:0)

尝试更简单的方法。 以两个向量作为参数。

template<typename T, typename A>
void foo( std::vector<T,A> const& t1, std::vector<T,A> const& t2 ) {

//do wtever you want

}