だから私は自動!=
を書きたい:テンプレートSFINAEでこの文を避けるにはどうすればいいですか?
template<typename U, typename T>
bool operator!=(U&& u, T&& t) {
return !(std::forward<U>(u) == std::forward<T>(t));
}
それは失礼です。だから私が言うタイプの特性クラスがある
// T() == U() is valid?
template<typename T, typename U, typename=void>
struct can_equal:std::false_type {};
template<typename T, typename U>
struct can_equal<
T,
U,
typename std::enable_if<
std::is_convertible<
decltype(std::declval<T>() == std::declval<U>()),
bool
>::value
>::type
>: std::true_type {};
を書く「bool
に変換型を返すt == u
有効なコードです」。
だから、私は!=
を改善:
template<typename U, typename T,
typename=typename std::enable_if<can_equal<T,U>::value>::type
>
bool operator!=(U&& u, T&& t) {
return !(std::forward<U>(u) == std::forward<T>(t));
}
と==
が存在する場合は、今では唯一の有効なオーバーライドです。悲しいことに、それは少し欲張りです:
struct test {
};
bool operator==(const test&, const test&);
bool operator!=(const test&, const test&);
それはほとんどすべてのtest() != test()
ではなく、上記の!=
が呼び出されるまでSNARFますよう。私はこれが望ましくないと思う - むしろ、==
に自動転送よりも明示的に!=
を呼んでネゲートしたいと思う。
template<typename T, typename U,typename=void>
struct can_not_equal // ... basically the same as can_equal, omitted
T != U
が有効であるかどうかをテストします。
だから、私はこの特性クラスを記述します。
次のように私たちは、その後!=
を強化:、あなたがそれを解析すると、「この文は偽である」と言う
template<typename U, typename T,
typename=typename std::enable_if<
can_equal<T,U>::value
&& !can_not_equal<T,U>::value
>::type
>
bool operator!=(U&& u, T&& t) {
return !(std::forward<U>(u) == std::forward<T>(t));
}
からT
とU
の間に存在していないoperator!=
がoperator!=
場合に限っT
とU
の間に存在します。
驚くべきことではありませんが、私がテストしたすべてのコンパイラは、これを与えたときにsegfaultsをテストしました。 (clang 3.2、gcc 4.8 4.7.2 intel 13.0.1)。 私がやっていることは違法だと思うが、私は標準的な参照を見たいと思う。(編集:!=
が適用されるかどうかを調べるために、無制限の再帰的テンプレート展開を誘導するため、私が行っていることは違法です。!=
が適用されるかどうかを確認する必要があります。 )。
しかし、私の質問:SFINAEベースのオーバーライドに、それが失敗するかどうかを決めるときに "自分"を無視する方法を教えてもらえませんか、何らかの形で自己参照の問題を取り除く方法はありますか?または、私のoperator!=
の優先順位を低くして、明示的に!=
が勝つようにしてください。
「!=
が存在しません」をチェックしていないものは、うまく動作しますが、グローバル名前空間に挿入するのと同じくらい無防備ではありません。
私の "魔法"なしでコンパイルするコード!=
は、 "魔法" !=
が導入されたときとまったく同じことをします。 !=
が無効である場合に限り、とbool r = !(a==b)
は私の "魔法" !=
がキックされていればよい。
脚注:あなたはtemplate<typename U, typename T> bool operator!=(U&& u, T&& t)
を作成する場合は、SFINAEは種類のすべてのペアは、それらの間の有効な!=
を持っていると思います。実際に!=
を呼び出すと、インスタンス化され、コンパイルに失敗します。さらに、とfoo a, b; a != b;
の方が適しているので、bool operator!=(const foo&, const foo&)
の機能を踏襲しています。私はこれらの無礼の両方をすることを検討します。
私はあなたが認識していると確信しているが、 ''から名前空間std :: rel_ops'は 'これの実用的な(ナイーブ)バージョンがあります。 –
非タイプのパラメータのデフォルトのテンプレート引数を入れ替えて、簡単にコピーできる場所にSSCCEを指定してください。 – Xeo
+1クレイジーなことをするためだけです。再帰SFINAE ...うわー:-P –