首先,我正在使用C++ 11(我的主题很糟糕).
我要做的是编写一个通用模板函数,它实现了通常sort_by在其他编程语言中调用的东西.它涉及精确计算一个范围的每个成员的任意标准,然后根据这些标准对该范围进行排序.这样的标准不一定是POD,它必须是低于可比性的.对于std::less不起作用的东西,调用者应该能够提供她自己的比较函子.
我已经成功编写了使用以下签名的函数:
template< typename Tcriterion
, typename Titer
, typename Tcompare = std::less<Tcriterion>
>
void
sort_by(Titer first, Titer last,
std::function<Tcriterion(typename std::iterator_traits<Titer>::value_type const &)> criterion_maker,
Tcompare comparator = Tcompare()) {
}
Run Code Online (Sandbox Code Playgroud)
它可以像这样使用:
struct S { int a; std::string b; double c; };
std::vector<S> s_vec{
{ 42, "hello", 0.5 },
{ 42, "moo!", 1.2 },
{ 23, "fubar", 0.2 },
};
sort_by1< std::pair<int, double> >(
s_vec.begin(), s_vec.end(),
[](S const &one_s) { return std::make_pair(one_s.a, one_s.c); }
);
Run Code Online (Sandbox Code Playgroud)
我不喜欢这种方法是我必须自己提供Tcriterion参数,因为编译器不能从lambda表达式中推断出该类型.因此,这不起作用:
sort_by1(s_vec.begin(), s_vec.end(), [](S const &one_s) { return std::make_pair(one_s.a, one_s.c); });
Run Code Online (Sandbox Code Playgroud)
clang 3.1和gcc 4.7.1都在这上面吠(gcc 4.7.1甚至在上面的代码上吠叫,所以我想我在这里做错了).
但是,如果我将lambda分配给std::function第一个,那么至少clang 3.1可以推导出该参数,这意味着它有效:
typedef std::pair<int, double> criterion_type;
std::function<criterion_type(S const &)> criterion_maker = [](S const &one_s) {
return std::make_pair(one_s.a, one_s.c);
};
sort_by1(s_vec.begin(), s_vec.end(), criterion_maker);
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:我如何更改我的函数签名,以便我不需要指定一个参数?并且(可能相关)我如何修复我的例子让它与gcc一起工作?
不要std::function与模板参数推导一起使用.实际上,很可能没有理由std::function在函数或函数模板参数列表中使用.通常,你不应该使用std::function; 它是一个非常专业的工具,非常擅长解决一个特定的问题.其余的时间,你可以完全放弃它.
在您的情况下,如果您使用多态仿函数来订购内容,则不需要模板参数推导:
struct less {
template<typename T, typename U>
auto operator()(T&& t, U&& u) const
-> decltype( std::declval<T>() < std::declval<U>() )
{ return std::forward<T>(t) < std::forward<U>(u); }
// operator< is not appropriate for pointers however
// the Standard defines a 'composite pointer type' that
// would be very helpful here, left as an exercise to implement
template<typename T, typename U>
bool operator()(T* t, U* u) const
{ return std::less<typename std::common_type<T*, U*>::type> {}(t, u); }
};
Run Code Online (Sandbox Code Playgroud)
然后你可以声明:
template<typename Iter, typename Criterion, typename Comparator = less>
void sort_by(Iter first, Iter last, Criterion crit, Comparator comp = less {});
Run Code Online (Sandbox Code Playgroud)
并comp(*ita, *itb)会做正确的事,也comp(crit(*ita), crit(*itb))还是什么,只要别人它是有意义的.
| 归档时间: |
|
| 查看次数: |
2702 次 |
| 最近记录: |