用模板将多个向量(函数的结果)合并为一个 [英] Combine multiple vectors (results of function) into one with template

查看:59
本文介绍了用模板将多个向量(函数的结果)合并为一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望有一个模板函数接受 vector< T> v 和函数op,将 T 映射到 vector< U> ,并希望合并对 v 的每个元素向量应用 f 以返回 vector< U>的结果; = [op(v [0])的元素,op(v [1])的元素...]。

I'd like to have a templated function taking in a vector<T> v and a function op, mapping T to vector<U> and would like to concatenate the results of applying f to every element vector of v to return a vector<U> = [ Elements of op(v[0]), Elements of op(v[1]) ...].

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

A working option I found was adding an example in the function to allow for template deduction:

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;  
}

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

But naturally I'd like to produce the same result with only the two parameters. My attempt [replacing U with 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;  
}

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

Unfortunately this didn't compile. I'm also worried of wasting time if op is complex method.

这给了:

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'有关。

... so it seems to be related to 'const'.

该变体将如何得到纠正?还有更好的选择吗?

How would this variant be corrected? Are there better alternatives?

推荐答案

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

Dereferencing a container iterator yields a reference (or a const reference, if the container was const), which is why decltype(*std::begin(op(*std::begin(c)))) yields const U& according to your compiler error (and not U).

您可以通过以下任一方法来解决此问题:使用 std :: remove_reference 再次引用(或者,如果您也想删除 const volatile std :: remove_cvref ),或仅询问向量其实际存储的内容:

You can fix this by either removing the reference again with std::remove_reference (or, if you want to also remove const and volatile, std::remove_cvref), or by just asking the vector for what it actually stores:

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

我已经继续并删除了不需要的 U&

I have gone ahead and removed the unneeded U& ex parameter.

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;  
}

演示

您还可以避免 decltype 通过命名来吟:

You can also avoid the triple repetition of the decltype chant by naming it:

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

这篇关于用模板将多个向量(函数的结果)合并为一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆