今天,我尝试实现基数排序。该函数必须具有两个变量:Begin Iterator和End Iterator,并且可以具有第三个变量:一些必须返回整数类型进行排序的函数。默认情况下,它必须是身份功能。
我的尝试看起来像(抱歉,代码看起来很长很脏,但这只是尝试):
.call()
当然,在编译时就会知道get_value的返回类型。
用法应为:
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; }) {
// ...
}
或者:
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; })
它甚至没有编译,我也不知道如何解决问题。怎么做?简单的例子:
std::vector<uint32_t> vec;
// ...
radix_sort(vec.begin(), vec.end());
编译器输出:
#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());
}
答案 0 :(得分:8)
解决此问题的简单方法是不具有默认功能,而是具有两个重载。这样一来,您就不必使用昂贵的std::function
了,只需编写几行样板代码即可。如果您使用
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; });
}
您将获得没有功能的默认“身份”,否则将获得确切的功能对象(如果提供了该对象)。
答案 1 :(得分:6)
为了将来的用户的利益,
我想指出的是C ++ 20引入了类std::identity
,
这有助于解决问题。
有了它的帮助
该代码可以重写为:
template <typename For, typename F = std::identity>
void radix_sort(For first, For end, F f = {})
{
/* ... */
}
您自己实施符合标准的程序非常容易 如果您没有C ++ 20,例如:
struct identity {
template <class T>
constexpr T&& operator()(T&& t) const noexcept
{
return std::forward<T>(t);
}
using is_transparent = void;
};