-
11-09-2019 - |
質問
私がしばしば遭遇状況、特に選別を行う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++?他の言語をより簡潔または優雅な文?
解決
やめたい場合、関数が返却 の場合 節をする必要がありません、明示的な else, にしていては保釈金を払って出て来ました。で保存する"インデントバレー":
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);
}
個人的に私が使用していない示唆=または私たちがここでお勧めしているように見えるのような演算子を==たい! - これはちょうどそれらを含むクラスをチェック少ないしを行うには、両方未満と同等の演算子を持つように引数/メンバーが必要です - オペレータその後、ちょうどあまりを使用してenoughtで、将来的にあなたの冗長性と潜在的な欠陥が保存されます。
。私はあなたが書く勧めます:
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解決策は、<のhref =「http://en.cppreference.com/w/cpp/utility/tuple/tie」を使用することですrel = "nofollowを">のの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
するように 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と同じことを思っていたし、この問題につまずきました。答えを読んだ後、私は唯一の比較のメンバーにのみlexicographicalMemberCompare
を使用していますoperator<
テンプレート関数を記述するためにjanmとRnRのに触発されています。あなたはできるだけ多くを指定することができるようにそれはまたブースト::タプルを使用していますあなたが好きなメンバー。ここでは、次のとおりです。
#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;
}
この希望は誰かに役立ちます。