私のソリューションは、すべてのクラスである:
struct FooComp {
using is_transparent = std::true_type;
struct FooProj {
std::string const& str;
FooProj(std::string const& sin):str(sin) {}
FooProj(const Foo& foo):str(foo.id) {}
FooProj(FooProj const&) = default;
friend bool operator<(FooProj lhs, FooProj rhs) {
return lhs.str < rhs.str;
}
};
bool operator()(FooProj lhs, FooProj rhs) const
{
return lhs<rhs;
}
};
これはサプリメントではありませんtタイプはstd::string
に変換できます。投影ベースの比較を行う際に
はしかし、私はこれを行う:
template<class F, class After=std::less<>>
auto order_by(F&& f, After&& after={}) {
return
[f=std::forward<F>(f), after=std::forward<After>(after)]
(auto&& rhs, auto&&lhs)->bool {
return after(f(decltype(lhs)(lhs)), f(decltype(rhs)(rhs)));
};
}
投影を取り、それのための比較関数を生成します。
template<class F>
struct as_transparent_t {
F f;
using is_transparent=std::true_type;
template<class Lhs, class Rhs>
bool operator(Lhs const& lhs, Rhs const& rhs)const{ return f(lhs, rhs); }
};
template<class F>
as_transparent_f<std::decay_t<F>>
as_transparent(F&& f) { return {std::forward<F>(f)}; }
は、私たちはプロジェクトを介して透明にすることができる:のみ投影を残し
as_transparent(order_by(some_projection));
我々はそれを透明にします。 C++ 14では
私たちは、モジュラーチャンクに物事を分解し
std::string const& foo_proj_f(std::string const& str) { return str; }
std::string const& foo_proj_f(Foo const& foo) { return foo.id; }
auto foo_proj = [](auto const& x)->decltype(auto){ return foo_proj_f(x); };
auto foo_order = as_transparent(order_by(foo_proj));
を行います。
C++ 17では、我々はif constexpr
を使用することができます。
auto foo_proj = [](auto const& x)->std::string const& {
if constexpr(std::is_same<decltype(x), std::string const&>{}) {
return x;
}
if constexpr(std::is_same<decltype(x), Foo const&>{}) {
return x.id;
}
};
auto foo_order = as_transparent(order_by(foo_proj));
またはif constexpr
バージョンよりも読みやすいかもしれ
auto foo_proj = overloaded{
[](std::string const& s)->decltype(auto){return s;},
[](Foo const& f)->decltype(auto){return f.id;}
};
を許可
template<class...Ts>
struct overloaded:Ts...{
using Ts::operator()...;
overloaded(Ts...ts):Ts(std::move(ts)...){}
};
template<class...Ts> overloaded -> overloaded<Ts...>;
。 (このバージョンはc++14またはc++11にも適用できます)。
テンプレートを使用していますか? (ちょっとランダムな推測:) – user1810087
@ Slava構造体のコンバージョンコンストラクタを宣言すれば十分です。 –
@VladfromMoscowしかし、それは単純ではない構造体 'Foo'のためのオーバーヘッドを持っていますか?したがって、これは全く同じソリューションではありません。もちろん、これは解決策の1つではありません。おそらくあなたはそれを答えにするべきです。 – Slava