我能否在构建新的变长模板参数时使用一个已有的变长模板参数?

3

我正在编写一个函数,它应该将一个可变元数的函数提升到一些类似于带有索引的 SQL 表的 std::vectors 中。我想将参数 f 应用于所有向量中具有相同 id 的元素集。我在模板推断方面遇到了问题,并且在这里(减去迭代器逻辑)进行了简化。我已经编写了我认为是合理的递归情况,但模板推断认为它不可行。

// Simple container type
template <typename T>
struct A {
  T x;
  T y;
  T z;
};

// Wrapper type to differentiate an extracted value from a container
// in template deduction
template <typename T>
struct B {
  T value;
};

// Base case. All A<Ts> have been extracted to B<Ts>.
template <typename F, typename... Ts>
void lift (F f, B<Ts> ...bs) {
  // Call f with extracted values
  f(bs.value...);
}

// Recursive case
template <typename F, typename T, typename... Ts, typename Us>
void lift (F f, A<T> a, A<Ts> ...as, B<Us> ...bs) {
  // Copy a value from the beheaded container A<T>.
  B<T> b = {a.x};
  // Append this B<T> to args and continue beheading A<Ts>.
  lift(f, as..., bs..., b);
}

// Test function
template <typename... Ts>
struct Test {
  void operator () (Ts...) {}
};

int main () {

  B<int> b = {1};
  // No errors for the base case
  lift(Test<>());
  lift(Test<int, int>(), b, b);

  // error: no matching function for call to 'lift'
  // The notes refer to the recursive case
  A<int> a = {1,0,0};
  lift(Test<int>(), a); // note: requires at least 3 arguments, but 2 were provided
  lift(Test<int>(), a, a); // note: requires 2 arguments, but 3 were provided
  lift(Test<int>(), a, a, b); // note: requires 2 arguments, but 4 were provided
}

这段代码有什么问题?

为了方便阅读和编写,忽略了这里的所有内容都是按值传递。 为什么不能编译?


as包是不可推导的,因为它不在最后一个参数位置。 - Luc Danton
1个回答

1

为什么不直接提取A和B的值呢?

template <typename T>
T extractValue(A<T> a)
{
    return a.x;
}
template <typename T>
T extractValue(B<T> b)
{
    return b.value;
}

template <typename F, typename... T>
void lift (F f, T... values) {
    f(extractValue(values)...);
}

此外,您最后两个测试案例无法编译,因为参数数量不正确。
lift(Test<int,int>(), a, a);
lift(Test<int,int,int>(), a, a, b);

为什么参数数量不对?当可变参数模板函数的目的是接受不同数量的参数时,我该如何提供错误数量的参数?我不理解。 - Samuel Danielson
我无法简单地提取这些值,因为每个容器中都有一个迭代器,而在调用 f 之间,其中一个迭代器可能会多次前进,而其他迭代器可能只前进一次。我需要分别处理每个迭代器的逻辑,因此我认为我需要将折叠和列表构建作为参数进行处理。 - Samuel Danielson
@SamuelDanielson: Test<int>() 只能接受一个参数。你提供了多于一个。 - kennytm
@SamuelDanielson:无法提取值→我不明白。请在问题中展示真实的代码。 - kennytm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接