C++ 使用STL对两个元素进行排序

C++ 使用STL对两个元素进行排序,c++,stl,C++,Stl,通常我有两个变量foo1和foo2,它们是数值类型。它们代表某物的边界 用户为他们提供值,但就像顽固不化的音乐家一样,不一定按正确的顺序 所以我的代码中到处都是这样的代码 if (foo2 < foo1){ std::swap(foo2, foo1); } if(foo2 > 。您需要重载比较运算符 例如,如果要比较foo1和foo2 template <class T> class Foo { private: int value; //

通常我有两个变量
foo1
foo2
,它们是数值类型。它们代表某物的边界

用户为他们提供值,但就像顽固不化的音乐家一样,不一定按正确的顺序

所以我的代码中到处都是这样的代码

if (foo2 < foo1){
    std::swap(foo2, foo1);
}
if(foo2

当然,这是一种惯用排序,其中两个元素在内存中不一定是连续的。这让我想知道:有没有一个STL一行程序可以实现这个功能?

没有,但是当你注意到你写了两次相同的代码时,是时候为它写一个函数了:

template<typename T, typename P = std::less<T>>
void swap_if(T& a, T& b, P p = P()) {
    if (p(a, b)) {
        using std::swap;
        swap(a, b);
    }
}
模板
如果(T&a、T&b、P=P())无效交换{
if(p(a,b)){
使用std::swap;
掉期(a、b);
}
}

没有,但是当您注意到您编写了两次相同的代码时,是时候为它编写一个函数了:

template<typename T, typename P = std::less<T>>
void swap_if(T& a, T& b, P p = P()) {
    if (p(a, b)) {
        using std::swap;
        swap(a, b);
    }
}
模板
如果(T&a、T&b、P=P())无效交换{
if(p(a,b)){
使用std::swap;
掉期(a、b);
}
}

如果你要比较的值的数据类型不是已经在C++中,那么P > >

。您需要重载比较运算符

例如,如果要比较foo1和foo2

template <class T>
class Foo { 
  private: 
    int value;     // value 

  public: 
    int GetValue() const {
        return value;
    }
}; 

bool operator<(const Foo& lhs, const Foo& rhs) {
    return (lhs.GetValue() < rhs.GetValue());
}
模板
类Foo{
私人:
int value;//value
公众:
int GetValue()常量{
返回值;
}
}; 

如果你要比较的值的数据类型不是C++中的,则BOOL运算符< P>。您需要重载比较运算符

例如,如果要比较foo1和foo2

template <class T>
class Foo { 
  private: 
    int value;     // value 

  public: 
    int GetValue() const {
        return value;
    }
}; 

bool operator<(const Foo& lhs, const Foo& rhs) {
    return (lhs.GetValue() < rhs.GetValue());
}
模板
类Foo{
私人:
int value;//value
公众:
int GetValue()常量{
返回值;
}
}; 

bool操作符我建议退一步,让类型系统为您完成这项工作:引入像
Bounds
(或
Interval
)这样的类型来解决这个问题。差不多

template <typename T>
class Interval {
public:
  Interval( T start, T end ) : m_start( start ), m_end( end ) {
    if ( m_start > m_end ) {
      std::swap( m_start, m_end );
    }
  }

  const T &start() const { return m_start; }
  const T &end() const { return m_end; }

private:
  T m_start, m_end;
};
模板
课间休息{
公众:
间隔(T开始,T结束):m_开始(开始),m_结束(结束){
如果(m_开始>m_结束){
标准::交换(m_开始,m_结束);
}
}
const T&start()const{return m_start;}
const T&end()const{return m_end;}
私人:
开始,结束;
};
这不仅集中了交换到排序的代码,还有助于很早就断言正确的顺序,这样您就不会一直传递两个元素,这意味着您甚至不需要在一开始就经常检查顺序


避免此问题的另一种方法是将边界表示为一对“起始值”和“长度”,其中“长度”是无符号值

我建议退一步,让类型系统为您完成这项工作:引入像
Bounds
(或
Interval
)这样的类型来解决这个问题。差不多

template <typename T>
class Interval {
public:
  Interval( T start, T end ) : m_start( start ), m_end( end ) {
    if ( m_start > m_end ) {
      std::swap( m_start, m_end );
    }
  }

  const T &start() const { return m_start; }
  const T &end() const { return m_end; }

private:
  T m_start, m_end;
};
模板
课间休息{
公众:
间隔(T开始,T结束):m_开始(开始),m_结束(结束){
如果(m_开始>m_结束){
标准::交换(m_开始,m_结束);
}
}
const T&start()const{return m_start;}
const T&end()const{return m_end;}
私人:
开始,结束;
};
这不仅集中了交换到排序的代码,还有助于很早就断言正确的顺序,这样您就不会一直传递两个元素,这意味着您甚至不需要在一开始就经常检查顺序

避免此问题的另一种方法是将边界表示为一对“起始值”和“长度”,其中“长度”是无符号值

返回最小和最大元素对。您可以将其与
std::tie
一起使用

#include <algorithm>
#include <tuple>
#include <iostream>

int main()
{
    int a = 7;
    int b = 5;
    std::tie(a, b) = std::minmax({a,b});
    std::cout << a << " " << b; // output: 5 7
}
#包括
#包括
#包括
int main()
{
INTA=7;
int b=5;
std::tie(a,b)=std::minmax({a,b});
std::cout返回一对最小和最大的元素。您可以将其与
std::tie
一起使用

#include <algorithm>
#include <tuple>
#include <iostream>

int main()
{
    int a = 7;
    int b = 5;
    std::tie(a, b) = std::minmax({a,b});
    std::cout << a << " " << b; // output: 5 7
}
#包括
#包括
#包括
int main()
{
INTA=7;
int b=5;
std::tie(a,b)=std::minmax({a,b});


std::cout减一?我可以用什么方法改进这个问题?减一?我可以用什么方法改进这个问题?这取决于,我们可以很容易地将原始示例放在一行
if(foo1第三个参数,
typename P=std::less
P=P()
?永远不要写重复的代码,除非这样做会产生更可读的代码,而且消除重复也不会带来任何好处。在这种情况下,它似乎毫无意义。@FrerichRaabe:同意,像
sort_2
这样的名称会更具解释性。这让我想起了这样的噱头:“IDE使做错事更容易。”。在这里,我们看到程序员自动化了错误的事情。代价是用许多“意外”抽象层次分割域。您希望避免这种情况。请参阅Raabe的答案。不过,根据情况,可以很容易地将原始示例放在一行
if(foo1第三个参数,
typename P=std::less
P=P()怎么样)
?永远不要写重复的代码,除非这样做会产生更可读的代码,而且消除重复也不会带来任何好处。在这种情况下,它似乎毫无意义。@FrerichRaabe:同意,像
sort_2
这样的名称会更具解释性。这让我想起了这样的噱头:“IDE使做错事更容易。”.在这里,我们看到程序员自动化了错误的事情。代价是用许多级别的“意外”将域分割开来抽象。您希望避免这种情况。请参阅Raabe的答案。为什么不使用
std::set
?它具有已排序的不变量。问题没有问如何编写
运算符为什么不使用
std::set
?它具有已排序的不变量。问题没有问如何编写
运算符指定它们不一定是重叠的内存中的断言。@Паааааафаааа首先不传递两个元素,而是引入一个强制断言的专用类型;这完全与值的存储方式无关。OP指定了它们