我正在编写一个模板,用于在编译时指定的索引中按元素对元组进行排序。我的代码有效,但使用起来很痛苦,因为我必须指定用于对元组元素进行排序的二进制函数的类型。
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);
}
因此,如果我想按元组中的第一个元素排序,我必须输入:
sort_by_index<std::less<char>, 0>(std::less<char>());
相反,我宁愿使用如下所示的界面来避免重复,但目前还没有编译。
sort_by_index<0>(std::less<char>());
我没有看到自动推断Index
的方式(并且没有必要),但sort_by_index
应该能够推断出BinaryFunction
的类型。
如何重写上述内容,以便我不需要指定BinaryFunction
的类型?
答案 0 :(得分:4)
Index
不可扣除,因此必须明确提供。明确提供的模板参数只能从左到右提供,而模板参数的排序并不重要,因此只需对它们进行重新排序以确保Index
是一个简单的修复方法。先走了:
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);
}
尽管如此,这并不令人满意,因为我们将两个看似无关的东西 - 我们用作比较器的二进制函数以及我们实际比较的数据混为一谈。我们必须在这里编写很多代码,这些代码基本上只是重复的样板。
在ranges proposal,Eric Niebler,Sean Parent和Andrew Sutton争论算法采取可调整的预测。如果你有一个C ++ 14编译器,我鼓励你实现它们,这样你就可以写下这样的东西:
// 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
答案 1 :(得分:0)
模板类型推导从右到左工作。如果必须指定最右边的模板参数,那么每个其他模板参数也必须如此。以下对上述的略微修改允许更清晰的界面。从本质上讲,Index
模板参数必须在BinaryFunction
之前,因为sort_by_index
无法自动推导Index
。
template <int Index, typename BinaryFunction>
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 <int Index, typename BinaryFunction>
sort_by_index_t<Index, BinaryFunction>
sort_by_index(const BinaryFunction& binary_function) {
return sort_by_index_t<Index, BinaryFunction>(binary_function);
}
以下编译:
sort_by_index<0>(std::less<char>());