使用模板将多个向量(函数的结果)组合成一个

Combine multiple vectors (results of function) into one with template

我想要一个接受 vector<T> v 和函数 op 的模板化函数,将 T 映射到 vector<U> 并希望连接应用 [= 的结果16=] 到 v 到 return 的每个元素向量 a vector<U> = [ op(v[0]) 的元素,op(v[1]) 的元素 ...] .

我发现的一个有效选项是在函数中添加一个示例以允许模板推导:

template <typename Container>
Container& concat(Container& c1, Container const& c2) {
  c1.insert(end(c1), begin(c2), end(c2));
  return c1;
}

template <typename Container, typename UnaryOperation, typename U>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op, U& ex)
    -> std::vector<U> {
  std::vector<U> v;
  for (auto& e : c) {
    std::vector<U> opv = op(e);
    concat(v, opv);
  }
  return v;  
}

但自然而然地,我想只用这两个参数产生相同的结果。 我的尝试[将U替换为decltype(*std::begin(op(*std::begin(c))))]:

template <typename Container, typename UnaryOperation, typename U>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op, U& ex)
    -> std::vector<decltype(*std::begin(op(*std::begin(c))))> {
  std::vector<decltype(*std::begin(op(*std::begin(c))))> v;
  for (auto& e : c) {
    std::vector<decltype(*std::begin(op(*std::begin(c))))> opv = op(e);
    concat(v, opv);
  }
  return v;  
}

不幸的是,这没有编译。如果 op 是复杂的方法,我也担心浪费时间。

这给了:

error: conversion from ‘std::vector<U>’ to non-scalar type ‘std::vector<const U&, std::allocator<const U&> >’ requested

error: forming pointer to reference type ‘const U&

... 所以它似乎与 'const'.

有关

如何更正此变体?有更好的选择吗?

取消引用容器迭代器会产生一个引用(或一个 const 引用,如果容器是 const),这就是为什么 decltype(*std::begin(op(*std::begin(c)))) 根据您的编译器错误产生 const U&(而不是 U).

您可以通过使用 std::remove_reference (or, if you want to also remove const and volatile, std::remove_cvref) 再次删除引用来解决这个问题,或者只询问向量它实际存储的内容:

decltype(*std::begin(op(*std::begin(c)))) -> typename decltype(op(*std::begin(c)))::value_type

我已经删除了不需要的 U& ex 参数。

template <typename Container, typename UnaryOperation>
inline auto to_vec_from_vectors(Container& c, UnaryOperation&& op)
    -> std::vector<typename decltype(op(*std::begin(c)))::value_type> {
  std::vector<typename decltype(op(*std::begin(c)))::value_type> v;
  for (auto& e : c) {
    std::vector<typename decltype(op(*std::begin(c)))::value_type> opv = op(e);
    concat(v, opv);
  }
  return v;  
}

Demo

您还可以通过命名来避免 decltype 颂歌的三次重复:

template <typename Container, typename UnaryOperation>
using applied_op_t = typename decltype(std::declval<UnaryOperation>()(*std::begin(std::declval<Container>())))::value_type;