【问题标题】:c++ recursive template resolution: flattening vectors of vectors elegantlyc++递归模板解析:优雅地展平向量的向量
【发布时间】:2019-09-06 09:38:48
【问题描述】:

考虑以下(简单的)C++ 代码,将对象从自定义列表类型传输到std::vector

template<class A> void transfer(std::vector<A>& target, const custom_list_type& source){
  for(const A& elem:source){
    target.push_back(elem);
  }
}

现在,假设有一个 std::vector 的此类自定义列表并想要展平结构,或者 std::vector 此类向量。天真地,我现在会继续编写这种类型的函数。

template<class A> void flatten_transfer(std::vector<A>& target, const std::vector<custom_list_type>& source){
  for(const auto& elem:source){
    flat_transfer(target,elem);
  }
}

template<class A> void flatten_transfer(std::vector<A>& target, const std::vector<std::vector<custom_list_type> >& source){
  for(const auto& elem:source){
    flat_transfer(target,elem);
  }
}

等等等等。但我看到这不是很优雅,因为我需要每个深度级别的这个函数的一个版本。我想有一种更优雅的方法可以使用一些模板魔法来解决这个问题,但我的知识还不够丰富,无法想出一个真正更好的解决方案。

使用模板抽象出矢量深度级别的“推荐”方法是什么,以便只需要编写 flatten_transfer 的单个实例?

【问题讨论】:

  • ot:最优雅的方法是首先不使用深度嵌套的容器;)
  • 输入总是std::vector ?或者您还需要其他容器类型?
  • 鉴于source 可以使用基于范围的for 进行迭代,transfer() 函数可以实现为target.insert(target.end(), source.begin(), source.end())。这同样可以用于您的第一个 flatten_transfer() 函数的主体。从那里开始第三次这样做是微不足道的。
  • @user463035818:输入始终是std::vector
  • @Peter:谢谢你的建议,这个建议其实很有用,但没有解决这个问题的核心部分(flatten_transfer 的两个变体如何扩展和统一)。

标签: c++ templates vector


【解决方案1】:

假设我正确理解了问题,以下函数模板在 C++17 及更高版本中可以很好地用于此目的。 当且仅当AB 相同时,此函数实例化target.push_back(elem)。 否则,这将进入下一个深度:

Live DEMO

template<
    class A,
    class B,
    template <class...> class Container,
    class... extras>
void flat_transfer(std::vector<A>& target, const Container<B, extras...>& source)
{
    for(const auto& elem : source)
    {
        if constexpr(std::is_same<A, B>::value){
            target.push_back(elem);
        }
        else{
            flat_transfer(target, elem);
        }
    }
}

这是一个用法示例:

std::vector<int> v{1,2,3};
std::set<std::vector<std::deque<int>>, std::greater<>> vv{{{4,5}, {6,7}, {8,9}}, {{10,11,12}, {13,14}, {15}}};

flat_transfer(v, vv);

// prints "1 2 3 10 11 12 13 14 15 4 5 6 7 8 9" 
for(const auto& i : v){
    std::cout << i << " ";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    相关资源
    最近更新 更多