部分模板类型推导 [英] Partial template type deduction

查看:47
本文介绍了部分模板类型推导的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个模板,用于在编译时指定的索引处按元组的元素对元组进行排序。我的代码可以工作,但是使用起来很麻烦,因为我必须指定用于对元组元素进行排序的二进制函数的类型。

  template< typename BinaryFunction,int Index> 
结构sort_by_index_t {
显式sort_by_index_t(const BinaryFunction& binary_function)
:binary_function(binary_function){}

模板< typename Tuple>
bool operator()(const Tuple& left,const Tuple& right)const {
return binary_function(std :: get< Index>(left),
std :: get< Index> (对));
}

private:
const BinaryFunction binary_function;
};

模板< typename BinaryFunction,int Index>
sort_by_index_t< BinaryFunction,Index>
sort_by_index(const BinaryFunction& binary_function){
return sort_by_index_t< BinaryFunction,Index>(binary_function);
}

因此,如果我想按元组中的第一个元素进行排序,键入:

  sort_by_index< std :: less< char> ;, 0>(std :: less< char>()) ; 

相反,我希望使用如下所示的界面来避免重复,但是它并没有

  sort_by_index< 0>(std :: less< char>());当前编译。 

我看不到自动推断 Index (这是不必要的),但是 sort_by_index 应该能够推断出 BinaryFunction 的类型。 / p>

如何重写上面的代码,这样就不必指定 BinaryFunction 的类型了?

解决方案

索引是不可推论的,因此必须明确提供。明确提供的模板参数只能从左到右提供,而模板参数的顺序对于推论并不重要,因此只需重新排序以确保 Index 首先:

  template< int索引,类型名称BinaryFunction> //仅此行需要更改
sort_by_index_t< BinaryFunction,Index>
sort_by_index(const BinaryFunction& binary_function){
return sort_by_index_t< BinaryFunction,Index>(binary_function);
}






之所以令人不满意,是因为我们要混合两个看似无关的东西-我们用作比较器的二进制函数,以及我们实际比较的数据。而且我们必须在这里编写很多代码,这些代码基本上只是重复的样板。



范围提议,埃里克·尼布勒,肖恩·父母和安德鲁·萨顿争辩说算法采用了可调用的投影。如果您使用的是C ++ 14编译器,建议您实现它们,以便您可以编写以下内容:

  //多态吸气剂
模板< size_t I>
auto getter(){
return [](auto&&元组){
return std :: get< I>(std :: forward< decltype(tuple)>(tuple ));
};
}

//仅将吸气剂用作投影
std :: sort(container_of_tuples,
std :: less< char> {},//此是二进制函数
getter< 0>()); //这是投影


I am writing a template meant to sort tuples by their elements at compile-time specified indices. I have code that works, but is a pain to use because I have to specify the type of the binary function used to sort the tuple elements.

template <typename BinaryFunction, int Index>
struct sort_by_index_t {
  explicit sort_by_index_t(const BinaryFunction& binary_function)
      : binary_function(binary_function) {}

  template <typename Tuple>
  bool operator()(const Tuple& left, const Tuple& right) const {
    return binary_function(std::get<Index>(left),
                           std::get<Index>(right));
  }

 private:
  const BinaryFunction binary_function;
};

template <typename BinaryFunction, int Index>
sort_by_index_t<BinaryFunction, Index>
sort_by_index(const BinaryFunction& binary_function) {
  return sort_by_index_t<BinaryFunction, Index>(binary_function);
}

So if I want to sort by the first element in the tuple, I have to type:

sort_by_index<std::less<char>, 0>(std::less<char>());

Instead, I'd rather have an interface such as the below to avoid duplication, but it does not currently compile.

sort_by_index<0>(std::less<char>());

I don't see a way to automatically deduce Index (and it would be unnecessary), but sort_by_index should be able to deduce the type of BinaryFunction.

How can I rewrite the above so that I do not need to specify the type of BinaryFunction?

解决方案

Index is non-deducible, so it must be explicitly provided. Explicitly provided template arguments can only be provided from left-to-right, whereas the ordering of the template arguments doesn't matter for deduction so it's a simple fix to just reorder them to make sure Index goes first:

template <int Index, typename BinaryFunction> // only this line needs to change
sort_by_index_t<BinaryFunction, Index>
sort_by_index(const BinaryFunction& binary_function) {
  return sort_by_index_t<BinaryFunction, Index>(binary_function);
}


That said, this is unsatisfying because we're conflating two seemingly unrelated things - the binary function that we're using as a comparator, and the data that we're actually comparing. And we have to write a lot of code here that's basically just repetitive boilerplate.

In the ranges proposal, Eric Niebler, Sean Parent, and Andrew Sutton argue for algorithms taking invokable projections. If you have a C++14 compiler, I'd encourage you to implement them so that you can just write something like:

// polymorphic getter
template <size_t I>
auto getter() {
    return [](auto&& tuple) {
        return std::get<I>(std::forward<decltype(tuple)>(tuple));
    };
}

// just use the getter as a projection
std::sort(container_of_tuples,
    std::less<char>{},  // this is the binary function
    getter<0>());       // this is the projection

这篇关于部分模板类型推导的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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