문제

나는 더 큰 구조를 비교하기 위해 일련의 필드를 비교하는 C ++의 정렬과 관련하여 상황, 특히 상황을 자주 만난다. 단순화 된 예 :

struct Car{
    Manufacturer make;
    ModelName model;
    Year year;
};

bool carLessThanComparator( const Car & car1, const Car & car2 ){
    if( car1.make < car2.make ){
        return true;
    }else if( car1.make == car2.make ){
        if( car1.model < car2.model ){
            return true;
        }else if( car1.model == car2.model ){
            if( car1.year < car2.year ){
                return true;
            }
        }
    }

    return false;
}

나의 본능적 접근은 특히 3 개 이상의 필드에서 번거롭게 보입니다. C ++ 에서이 일련의 비교를 어떻게 구성 하시겠습니까? 다른 언어는 더 간결하거나 우아한 구문을 제공합니까?

도움이 되었습니까?

해결책

당신의 기능이 만약에 조항, 명시 적이 필요하지 않습니다 또 다른, 그것은 이미 쫓겨 났을 것입니다. "Indent Valley"를 절약 할 수 있습니다.

bool carLessThanComparator( const Car & car1, const Car & car2 ) {
    if( car1.make < car2.make )
        return true;

    if ( car1.make != car2.make )
        return false;

    if( car1.model < car2.model )
        return true;

    if( car1.model != car2.model )
        return false;

    if( car1.year < car2.year )
        return true;

    return false;
}

나는 Markusq의 Lispish 단락 접근법도 좋아합니다.

다른 팁

이런 일이 많이 발생하면 이와 같은 템플릿을 공통 헤더에 넣을 수 있습니다.

template<typename T, typename A1, typename A2, typename A3>
bool
do_less_than(
        const typename T& t1,
        const typename T& t2,
        const typename A1 typename T::* a1,
        const typename A2 typename T::* a2,
        const typename A3 typename T::* a3)
{
    if ((t1.*a1) < (t2.*a1)) return true;
    if ((t1.*a1) != (t2.*a1)) return false;
    if ((t1.*a2) < (t2.*a2)) return true;
    if ((t1.*a2) != (t2.*a2)) return false;
    return (t1.*a3) < (t2.*a3);
}

필요에 따라 다른 수의 인수에 대해 다른 템플릿을 추가하십시오. 함수보다 적은 각각에 대해 다음과 같은 작업을 수행 할 수 있습니다.

bool carLessThanComparator(const Car& car1, const Car& car2)
{
    return do_less_than(car1, car2, &Car::make, &Car::model, &Car::year);
}

개인적으로 나는 여기서 추천하는 것처럼! = 또는 == 운영자를 사용하지 않는 것이 좋습니다. 이것은 인수/멤버가 덜 동등한 연산자와 동등한 연산자가 모두 포함하는 클래스를 확인해야합니다. 연산자가 충분하지 않으며 향후 중복성 및 잠재적 결함을 절약 할 수 있습니다.

나는 당신이 쓰기를 제안합니다 :

bool operator<(const Car &car1, const Car &car2) 
{
    if(car1.make < car2.make)
        return true;
    if(car2.make < car1.make)
        return false;

    if(car1.model < car2.model)
        return true;
    if(car2.model < car1.model)
        return false;

    return car1.year < car2.year;
}

나는 그것이 오래된 질문이라는 것을 알고 있지만 미래의 방문자에게는 : 현대 C ++ 11 솔루션은 사용하는 것입니다. std :: 넥타이

struct Car{
    Manufacturer make;
    ModelName model;
    Year year;
};

bool operator<(Car const& lhs, Car const& rhs)
{
    return std::tie(lhs.make, lhs.model, lhs.year) < std::tie(rhs.make, rhs.model, rhs.year);
}

std::tie 구조물을 a로 변환합니다 std::tuple 위의 비교 연산자가 std::tuple::operator<. 이것은 회원들이 마샬링되는 순서와 관련하여 사전 사전 비교를합니다. std::tie.

어휘 비교는이 질문에 대한 다른 솔루션과 같은 방식으로 단락됩니다. 그러나 C ++ 람다 표현 내에서 즉시 정의 할 수있을 정도로 간결합니다. 개인 데이터 구성원이있는 클래스의 경우 클래스 내에서 다음과 같이 정의됩니다. friend 기능.

bool carLessThanComparator( const Car & car1, const Car & car2 ){
    return (
      ( car1.make  < car2.make  ) or (( car1.make  == car2.make  ) and
      ( car1.model < car2.model ) or (( car1.model == car2.model ) and
      ( car1.year  < car2.year  ) 
      )));

- Markusq

개인적으로, 나는 ==, <,>를 무시하고 다른 운영자가 필요합니다. 그것은 비교가 아니라 비교를해야 할 때 코드를 정리할 수 있습니다. 실제 비교 자체를 위해 Crashworks가 말한 것과 유사하게 글을 쓸 것입니다.

bool operator<(const Car &car1, const Car &car2) {
    if(car1.make < car2.make)
        return true;
    if(car1.make != car2.make)
        return false;
    if(car1.model < car2.model)
        return true;
    if(car1.model != car2.model)
        return false;
    return car1.year < car2.year;
}

나는 OP와 같은 것을 궁금해 하고이 질문을 우연히 발견했습니다. 답을 읽은 후 Janm과 RNR에서 영감을 얻었습니다. lexicographicalMemberCompare 만 사용하는 템플릿 함수 operator< 비교 멤버에. 또한 사용합니다 부스트 :: 튜플 원하는만큼의 회원을 지정할 수 있습니다. 여기있어:

#include <iostream>
#include <string>
#include <boost/tuple/tuple.hpp>

template <class T, class Cons>
struct LessThan
{
    static bool compare(const T& lhs, const T& rhs, const Cons& cons)
    {
        typedef LessThan<T, typename Cons::tail_type> NextLessThan;
        typename Cons::head_type memberPtr = cons.get_head();
        return lhs.*memberPtr < rhs.*memberPtr ?
            true :
            (rhs.*memberPtr < lhs.*memberPtr  ?
                false :
                NextLessThan::compare(lhs, rhs, cons.get_tail()));
    }
};

template <class T>
struct LessThan<T, class boost::tuples::null_type>
{
    static bool compare(const T& lhs, const T& rhs,
                        const boost::tuples::null_type& cons)
    {
        return false;
    }
};

template <class T, class Tuple>
bool lexicographicalMemberCompare(const T& lhs, const T& rhs,
                                  const Tuple& tuple)
{
    return LessThan<T, typename Tuple::inherited>::compare(lhs, rhs, tuple);
}

struct Car
{
    std::string make;
    std::string model;
    int year;
};

bool carLessThanCompare(const Car& lhs, const Car& rhs)
{
    return lexicographicalMemberCompare(lhs, rhs,
        boost::tuples::make_tuple(&Car::make, &Car::model, &Car::year));
}

int main()
{
    Car car1 = {"Ford", "F150", 2009};
    Car car2 = {"Ford", "Escort", 2009};
    std::cout << carLessThanCompare(car1, car2) << std::endl;
    std::cout << carLessThanCompare(car2, car1) << std::endl;
    return 0;
}

이것이 누군가에게 유용하기를 바랍니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top