テンプレート化されたクラスがあります
template <typename T>
class SometimesComparable
{
public:
T x1;
T x2;
// Other functionally provided unconditionally
// ...
// To be provided only if T provides operator<
// bool operator<(SometimesComparable const & other) const
// {
// return x1 < other.x1 && x2 < other.x2;
// }
};
bool operator<()
テンプレートパラメータも提供する場合にのみ提供する必要がありますbool operator<()
SFINAEを使用した同様の質問/回答を読みましたが、このケースにアイデアを適応させることができなかったため、理解できなかったことがあるはずです。
それらの答えを真似て私はクラスを持っています
template <typename T>
class HasLessThan
{
private:
typedef char YesType[1];
typedef char NoType[2];
template <typename C> static YesType& test( decltype(&C::operator<) );
template <typename C> static NoType& test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(YesType) };
};
test
そのメンバーを介してそのメソッドを使用してvalue
、クラスがT
提供するかどうかを検出しますoperator<
。
SometimesComparable
私が定義しているクラスの中で
typename std::enable_if<HasLessThan<T>::value, bool>::type
operator<(ConditionalMethodProvided &other)
{
return x1 < other.x1 && x2 < other.x2;
}
次に、テスト用に、機能する用途のために、クラスがあります
class TypeWithLessThan
{
public:
int x;
TypeWithLessThan(int x) : x(x) {};
bool operator<(TypeWithLessThan &other) {return x < other.x;};
};
int main(int argc, char *argv[])
{
ConditionalMethodProvided C(TypeWithLessThan(2), TypeWithLessThan(3));
ConditionalMethodProvided D(TypeWithLessThan(5), TypeWithLessThan(7));
std::cout << (C < D) << std::endl;
return 0;
}
質問部分:これは問題ありません。さて、私が見逃しているのは、そのような実装はどうあるべきかということです
int main(int argc, char *argv[])
{
ConditionalMethodProvided C(2, 3);
ConditionalMethodProvided D(5, 7);
std::cout << (C < D) << std::endl;
return 0;
}
また、正常にコンパイルされます。
SometimesComparable
友達メソッドに追加してみました
friend
typename std::enable_if<HasLessThan<T>::value, bool>::type
operator<(ConditionalMethodProvided & a1, ConditionalMethodProvided &a2)
{
return a1.x1 < a2.x1 && a1.x2 < a2.x2;
};
最初のものoperator<
と友人のものの両方があると、あいまいなオーバーロードが作成さConditionalMethodProvided<int, int>
れます。それがないと、の比較がコンパイルされません。
私は両方int
とTypeWithLessThan
働きたいです。
編集:
単一のブロック内のコード。
#include <iostream>
#include <type_traits>
template <typename T>
class HasLessThan
{
private:
typedef char YesType[1];
typedef char NoType[2];
template <typename C> static YesType& test( decltype(&C::operator<) );
template <typename C> static NoType& test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(YesType) };
};
template <typename T>
class ConditionalMethodProvided
{
public:
T x1;
T x2;
ConditionalMethodProvided(T&& a1, T&& a2) : x1(a1), x2(a2) {};
// This and the next method may not be needed at the same time.
typename std::enable_if<HasLessThan<T>::value, bool>::type
operator<(ConditionalMethodProvided &other)
{
return x1 < other.x1 && x2 < other.x2;
};
template <typename U,
std::enable_if_t<std::is_same_v<U, T>, bool> = true>
auto operator< (ConditionalMethodProvided<U> & oth)
-> decltype( std::declval<U>() < std::declval<U>(), bool{} )
{ return x1 < oth.x1 && x2 < oth.x2; }
};
class TypeWithLessThan
{
public:
int x;
TypeWithLessThan(int x) : x(x) {};
bool operator<(TypeWithLessThan &other) {return x < other.x;};
};
int main(int argc, char *argv[])
{
// The question is how to to make the next two types, int and TypewithLessThan both make the templated class ConditionalMethodProvided to provide the operator< method.
ConditionalMethodProvided C(TypeWithLessThan(2), TypeWithLessThan(3));
ConditionalMethodProvided D(TypeWithLessThan(5), TypeWithLessThan(7));
std::cout << (C < D) << std::endl;
ConditionalMethodProvided E(2,3);
ConditionalMethodProvided F(5,7);
std::cout << (E < F) << std::endl;
return 0;
}
次のようにどうですか?
template <typename T>
class SometimesComparable
{
public:
T x1;
T x2;
template <typename U,
std::enable_if_t<std::is_same_v<U, T>, bool> = true>
auto operator< (SometimesComparable<U> const & oth)
-> decltype( x1 < oth.x1, bool{} )
{ return x1 < oth.x1 && x2 < oth.x2; }
};
つまり... SFINAEでメソッドを有効/無効にする場合は、メソッドをテンプレートにする必要があるため、
template <typename U>
bool operator< (SometimesComparable<U> const & oth)
{ /* something */ }
しかし、私はあなたがそれをしたいと仮定U
してT
、あなたがこのthrougを課すことができるように、同じタイプですstd::enable_if_t
template <typename U,
std::enable_if_t<std::is_same_v<U, T>, bool> = true>
bool operator< (SometimesComparable<U> const & oth)
{ /* something */ }
ここで、SFINAEで演算子を有効にする必要がありますx1 < oth.x1
(演算子が定義されている場合U
)。したがってauto
、末尾の戻り値の型とを使用してdecltype()
、次のように記述できます。
auto operator< (SometimesComparable<U> const & oth)
-> decltype( x1 < oth.x1, bool{} )
{ /* something */ }
または単にdecltype( x1 < oth.x1 )
それが価値をx1 < oth.x1
与えると確信しているbool
場合。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加