[英]Define a function in function declaration using std::iterator traits and auto
Today I tried to implement radix sort. 今天我尝试实现基数排序。 The function must have two variables: begin iterator and end iterator, and can have third: some function that must return the integer type to sort by.
该函数必须有两个变量:begin iterator和end iterator,并且可以有第三个:一些函数必须返回整数类型才能排序。 By default it must be the identity function.
默认情况下,它必须是身份功能。
My tries look like (sorry, code looks very long and dirty, but it's just a try): 我的尝试看起来像(对不起,代码看起来很长很脏,但它只是一个尝试):
template<class ForwardIt>
void radix_sort(
ForwardIt first,
ForwardIt last,
std::function<auto(typename std::iterator_traits<ForwardIt>::value_type)> get_value =
[](const typename std::iterator_traits<ForwardIt>::value_type& x){ return x; }) {
// ...
}
The returning type of get_value, of course, will be known in compilation time . 当然,返回类型的get_value将在编译时知道 。
Usage should be: 用法应该是:
std::vector<std::pair<uint32_t, std::string>> vec;
// ...
radix_sort(vec.begin(), vec.end(), [](const std::pair<uint32_t, std::string>& x){ return x.first; })
Or: 要么:
std::vector<uint32_t> vec;
// ...
radix_sort(vec.begin(), vec.end());
It doesn't even compile and I don't know how to solve the problem. 它甚至没有编译,我不知道如何解决问题。 How to do it?
怎么做? Simple example:
简单的例子:
#include <bits/stdc++.h>
template<class ForwardIt>
void radix_sort(
ForwardIt first,
ForwardIt last,
std::function<auto(typename std::iterator_traits<ForwardIt>::value_type)> get_value =
[](const typename std::iterator_traits<ForwardIt>::value_type& x){ return x; }) {
// ...
}
int main()
{
std::vector<std::pair<uint32_t, std::string>> vec(10);
radix_sort(vec.begin(), vec.end());
}
Compiler output: 编译器输出:
source_file.cpp:17:37: error: no matching function for call to ‘radix_sort(std::vector<unsigned int>::iterator, std::vector<unsigned int>::iterator)’
radix_sort(vec.begin(), vec.end());
^
source_file.cpp:6:6: note: candidate: template<class ForwardIt, class auto:1> void radix_sort(ForwardIt, ForwardIt, std::function<auto:1(typename std::iterator_traits<_Iter>::value_type)>)
void radix_sort(
^
source_file.cpp:6:6: note: template argument deduction/substitution failed:
source_file.cpp:17:37: note: couldn't deduce template parameter ‘auto:1’
radix_sort(vec.begin(), vec.end());
The easy way to fix this is to not have a default function and instead have two overloads. 解决这个问题的简单方法是没有默认函数,而是有两个重载。 This lets you get rid of using a
std::function
, which is expensive, at the cost of writing a couple lines of boiler plate code. 这可以让你摆脱使用
std::function
,这是昂贵的,代价是编写几行样板代码。 If you use 如果你使用
template<class ForwardIt, class Func>
void radix_sort(ForwardIt first, ForwardIt last, Func get_value) {
// ...
}
template<class ForwardIt>
void radix_sort(ForwardIt first, ForwardIt last) {
radix_sort(first, last, [](const typename std::iterator_traits<ForwardIt>::value_type& x){ return x; });
}
the you get the default "identity" with no function, and you get the exact function object otherwise if one is provided. 你得到没有功能的默认“身份”,你得到了确切的功能对象,否则提供了一个。
For the benefit of future users, I would like to point out that C++20 introduces the class std::identity
, which aids in solving the problem. 为了未来用户的利益,我想指出C ++ 20引入了类
std::identity
,它有助于解决问题。 With its help, the code can be rewritten as: 在它的帮助下,代码可以重写为:
template <typename For, typename F = std::identity>
void radix_sort(For first, For end, F f = {})
{
/* ... */
}
And it is very easy to implement a standard-conforming one yourself if you don't have C++20, like this: 如果你没有C ++ 20,很容易自己实现一个符合标准的,如下所示:
struct identity {
template <class T>
constexpr T&& operator()(T&& t) const noexcept
{
return std::forward<T>(t);
}
using is_transparent = void;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.