3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

構造体(aggregate) に 比較関数を極力自動で生やす

3
Posted at

よくある問題

C++の構造体には operator==とか生えていない。1
そのため、std::setやuniqを利用するには自分でoperator<などを定義する必要がある。
しかし困ったことにめんどい。今回はこれを何とかしたい

解決案

解決するには以下の二つのものを組み合わせればよい

  • 構造体を比較する方法
  • 関数を構造体に結び付ける方法(極力低コストに)

構造体を比較する

  1. ココ などを参考に構造体をtupleに変換する関数を作る
  2. 1で構造体をtupleに変換して 比較する関数を作る

関数を構造体に結び付ける

やり方は2つある

  1. 構造体をwrapするhelperを作る
  2. 構造体を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);
}
  1. C++20では生えてくるといわれているが、人生と締め切りは短いので2020年とか待てない

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?