よくある問題
C++の構造体には operator==とか生えていない。1
そのため、std::setやuniqを利用するには自分でoperator<などを定義する必要がある。
しかし困ったことにめんどい。今回はこれを何とかしたい
解決案
解決するには以下の二つのものを組み合わせればよい
- 構造体を比較する方法
- 関数を構造体に結び付ける方法(極力低コストに)
構造体を比較する
- ココ などを参考に構造体をtupleに変換する関数を作る
- 1で構造体をtupleに変換して 比較する関数を作る
関数を構造体に結び付ける
やり方は2つある
- 構造体をwrapするhelperを作る
- 構造体をADLの呼び出し対象にするclassをつくる
構造体をwrapする
構造体をwrapするhelperをつかう
https://wandbox.org/permlink/GsnOppgzrVCjIwXk
lib.hpp
template<class S>
struct Wrap:S{
friend bool operator<(Wrap const &lhs, Wrap const &rhs){
return to_tie(lhs) < to_tie(rhs);
}
};
main.cpp
struct StructImpl{
int x;
std::string y;
};
using Struct=Wrap<StructImpl>;
int main(){
Struct a={1,""}, b={1,"b"};
assert(std::is_aggregate<Struct>());
assert(a<b);
}
構造体をADLの呼び出し対象にする
構造体をtemplateで作り、helper classを指定。ADL呼び出しの対象にする
https://wandbox.org/permlink/9xNFtLBkI01cx9M7
lib.hpp
struct Hook{
template<class T>
friend bool operator<(T const &lhs, T const &rhs){
return to_tie(lhs) < to_tie(rhs);
}
};
main.cpp
template<class>
struct StructImpl{
int x;
std::string y;
};
using Struct = StructImpl<Hook>;
int main(){
Struct a={1,""}, b={1,"b"};
assert(std::is_aggregate<Struct>());
assert(a<b);
}
-
C++20では生えてくるといわれているが、人生と締め切りは短いので2020年とか待てない ↩