【发布时间】:2019-09-10 12:24:17
【问题描述】:
我有一个模板类
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) };
};
通过其成员value 使用其方法test 检测类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< 和朋友的 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;
}
【问题讨论】:
标签: c++ templates c++17 sfinae