Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 指针指向成员作为比较器的std算法;“关键”;_C++_Algorithm_C++11_Pointer To Member - Fatal编程技术网

C++ 指针指向成员作为比较器的std算法;“关键”;

C++ 指针指向成员作为比较器的std算法;“关键”;,c++,algorithm,c++11,pointer-to-member,C++,Algorithm,C++11,Pointer To Member,我经常发现自己使用std::sort,std::max_元素,以及类似的lambda来调用成员函数 std::vector<MyType> vec; // populate... auto m = std::max_element(std::begin(vec), std::end(vec), [](const MyType& a, const MyType& b) { return a.val() < b.val()}) 并按对象的val()s对对象

我经常发现自己使用
std::sort
std::max_元素
,以及类似的lambda来调用成员函数

std::vector<MyType> vec;
// populate...
auto m = std::max_element(std::begin(vec), std::end(vec),
    [](const MyType& a, const MyType& b) { return a.val() < b.val()})
并按对象的
val()
s对对象进行排序。我忽略了stdlib的某个部分,它能帮助我解决这个问题吗?还是另一种简单的方法?我想让这是什么排序或搜索尽可能明显


我知道仅仅
&MyType::val
是不够的,我正在寻找一种可以包装它的东西,或者提供类似的功能而不模糊其含义的东西。

一旦重载
操作符你可以使用
std::mem\fn
(或者
std::tr1::mem\fn


请参见

模板比较器可以帮助您:

template <typename StructureType,
          typename MemberType,
          MemberType StructureType::*member>
bool comparator(const StructureType& the_first, const StructureType& the_second)
{
  return the_first.*member < the_second.*member;
}
模板
布尔比较器(const-StructureType&第一个,const-StructureType&第二个)
{
返回第一个.*成员<第二个.*成员;
}

一点类型特征魔法当然可以让您避免编写类型。

您可以通过引入任何新函数(模板化或非模板化)来做到这一点

使用
bind
std::less

auto m = std::max_element(vec.begin(), vec.end(), 
    bind(less<>(), bind(&MyType::val, _1), bind(&MyType::val, _2)));
auto m=std::max_元素(vec.begin(),vec.end(),
绑定(less(),绑定(&MyType::val,_1),绑定(&MyType::val,_2));

为避免使用
std::mem\u fn
而对sehes答案进行的改进是为
compare\u by
函数提供一个指向成员重载的指针

示例用法

std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field));
std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field, std::greater<>{}));
std::sort(std::begin(vec)、std::end(vec)、compare_by(&MyType::field));
std::sort(std::begin(vec),std::end(vec),compare_by(&MyType::field,std::greater{}));
要实现的代码

#include <functional> // std::less
#include <utility> // std::move
#include <type_traits> // std::is_invocable_r
// Forward declaration
template<typename R, typename T, typename F = std::less<R>>
auto compare_by(R T::*, F = F{});

// Implementation
namespace detail {
template<typename T, typename F>
struct compare_by_t;

template<typename R, typename T, typename F>
struct compare_by_t<R T::*, F> : private F
{
    compare_by_t(F&& f, R T::*m): F{std::move(f)}, _member{m} {}
    R T::* _member;
    bool operator()(T const& x, T const& y) const
    {
        return F::operator()(x .* _member, y .* _member);
    }
};
} // detail

template<typename R, typename T, typename F>
auto compare_by(R T::* member, F f)
{
    static_assert(std::is_invocable_r<bool, F, R, R>::value);
    return detail::compare_by_t<R T::*, F>{ std::move(f), member };
}
#包含//标准::更少
#include//std::move
#include//std::是否可开票
//远期申报
模板
自动比较(rt::*,F=F{});
//实施
名称空间详细信息{
模板
按t进行结构比较;
模板
结构比较\u by\u t:private F
{
用{std::move(F)},{m}成员{m}比较
R T::*\U成员;
布尔运算符()(T常量和x,T常量和y)常量
{
返回F::operator()(x.*.\u成员,y.*.\u成员);
}
};
}//细节
模板
自动比较依据(R T::*成员,F)
{
静态断言(std::is\u invocable\u r::value);
返回detail::compare_by_t{std::move(f),member};
}

因为说某事物比另一事物小往往没有意义。如果我想按工资对员工进行分类,那就意味着要重载
操作符,而我想lambda是你能期望的最短的可能性。当然,你也可以用
std::bind
std::less
进行叠加,但这将更难理解,imo。好吧,这是一个有价值的选择,但是(@Ryan)请告诉我为什么这应该比一行lambda更好?它的意思是这样的(我在阅读你的建议之前已经纠正了它)。。。我在这里问他,我猜他是选民中的一员。“当然,我只是停留在上下文中,考虑不使用LAMBDAS为前提。我也会使用一个,除非我有std::算法在使用诸如
less
/
greater
/
greater\u equal
等操作之间交替使用,并且
std::
使我的生活更轻松。在这里转发是毫无意义的。一次移动并不会比什么都不做增加任何效率,而这正是当你只是通过引用传递时所得到的。此版本的C++11之前版本中没有副本。为什么要添加移动呢?在库代码中尽可能完美地向前移动可能是一个“好”习惯。但在可能的情况下,思考自己在做什么可能是一个“更好”的习惯。其中
less
是一个C++1y功能。@dyp在VS2013中工作,使其
less
在g++4.8中工作。是的,这是MSVC支持的“提前”功能之一,如
make_unique
。IIRC都是我的微软员工提出的。很好。我喜欢
std::bind
。然而,在这种情况下,lambda显然是优越的(这仍然重复相同的部分)。此外,功能组合的嵌套绑定可能会非常笨拙和令人惊讶(,)+但是,1表示信息丰富。注:我想不需要
val()
成员
auto m = std::max_element(vec.begin(), vec.end(), 
    bind(less<>(), bind(&MyType::val, _1), bind(&MyType::val, _2)));
std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field));
std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field, std::greater<>{}));
#include <functional> // std::less
#include <utility> // std::move
#include <type_traits> // std::is_invocable_r
// Forward declaration
template<typename R, typename T, typename F = std::less<R>>
auto compare_by(R T::*, F = F{});

// Implementation
namespace detail {
template<typename T, typename F>
struct compare_by_t;

template<typename R, typename T, typename F>
struct compare_by_t<R T::*, F> : private F
{
    compare_by_t(F&& f, R T::*m): F{std::move(f)}, _member{m} {}
    R T::* _member;
    bool operator()(T const& x, T const& y) const
    {
        return F::operator()(x .* _member, y .* _member);
    }
};
} // detail

template<typename R, typename T, typename F>
auto compare_by(R T::* member, F f)
{
    static_assert(std::is_invocable_r<bool, F, R, R>::value);
    return detail::compare_by_t<R T::*, F>{ std::move(f), member };
}