我可以在这里使用模板专业化或类型强制吗?

时间:2015-10-20 07:12:46

标签: c++ functional-programming c++14 move-semantics rvalue-reference

我有一个现有的模板,用于将慢速函数映射到集合(使用同名的clojure函数的样式),我希望加速这些函数"移动语义"这个有用的博客文章的味道不是我:http://blog.knatten.org/2012/11/02/efficient-pure-functional-programming-in-c-using-move-semantics/

我写的这段旧代码对我很有用:

getFileToStream

由于我愿意提交丢弃输入集合,因此我应该能够在in_type与out_type相同的情况下通过写入c而不是分配全新来加快速度。采集。我尝试了模板专业化,但编译器在特殊情况下无法选择,我无法提出修复。这是我尝试一些手法:

template <typename function,
      template <typename...> class collection,
      typename in_type,
      typename... types,
      typename out_type = 
        typename std::result_of<function(in_type)>::type>
static collection<out_type> pmap(
  const function& f, const collection<in_type, types...>& c)  {
  collection<out_type> result;
  if(!c.empty())  {
    result = collection<out_type>(c.size());   
    __gnu_parallel::transform(c.cbegin(),c.cend(),result.begin(),f);
  }
  return result;
}

我想有一些黑客可以让编译器接受result = c(尽管因为周围的if语句而无论如何都不应该关心),但这样的投射让我感到不安。有关如何修复此问题或为写入案例添加专门化模板的任何建议吗?

1 个答案:

答案 0 :(得分:2)

typeid是一个运行时构造,因此您尝试在运行时而不是编译时选择行为。

您可以编写两个重载并使用std::enable_if选择正确的重载:

template <typename function,
      template <typename...> class collection,
      typename in_type,
      typename... types,
      typename out_type = 
        typename std::result_of<function(in_type)>::type,
      typename std::enable_if<!std::is_same<in_type, out_type>::value>::type* = nullptr>
static collection<out_type> pmap(
  const function& f, collection<in_type, types...>&& c)  {
  collection<out_type> result;
  result.reserve(c.size());
  __gnu_parallel::transform(c.cbegin(),c.cend(),std::back_inserter(result),f);


  return result;
}

template <typename function,
      template <typename...> class collection,
      typename in_type,
      typename... types,
      typename out_type = 
        typename std::result_of<function(in_type)>::type,
      typename std::enable_if<std::is_same<in_type, out_type>::value>::type* = nullptr>
static collection<out_type,types...> pmap(
  const function& f, collection<in_type, types...>&& c)  {
  __gnu_parallel::transform(c.begin(),c.end(),c.begin(),f);

  return std::move(c);
}