EqualityComparable 特质解释
EqualityComparable trait explanation
阅读第二版 C++ 模板的第 22 章,我试图理解 EqualityComparable 特性的实现。但是我不明白编译器是如何决定是否激活回退的。
除此之外还有两个只声明但程序编译运行的函数。这对我来说很奇怪。
这是代码。
头文件IsEqualityComparable.hpp
#include <utility> // for declval()
#include <type_traits> // for true_type and false_type
template<typename T>
class IsEqualityComparable
{
private:
// test convertibility of == and ! == to bool:
static void* conv(bool); // to check convertibility to bool
template<typename U>
static std::true_type test(decltype(conv(std::declval<U const&>() ==
std::declval<U const&>())),
decltype(conv(!(std::declval<U const&>() ==
std::declval<U const&>())))
);
// fallback:
template<typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(nullptr,
nullptr))::value;
};
源文件如下
#include <iostream>
#include <exception>
#include <utility>
#include <functional>
#include "isequalitycomparable.hpp"
template<typename T,
bool EqComparable = IsEqualityComparable<T>::value>
struct TryEquals
{
static bool equals(T const& x1, T const& x2) {
std:: cout << "IsEqualityComparable equals::"<<std::endl;
return x1 == x2;
}
};
class NotEqualityComparable : public std::exception
{
};
template<typename T>
struct TryEquals<T, false>
{
static bool equals(T const& x1, T const& x2) {
std:: cout << "Throw::"<<std::endl;
throw NotEqualityComparable();
}
};
void foo(int)
{
}
void bar(int)
{
}
class A
{
public:
A() = default;
friend bool operator ==(A a1 , A a2)
{
return true;
}
};
int main()
{
std:: cout << "Enter" << std::endl;
std::function<void(int)> f = foo;
std::function<void(int)> f2 = f;
std:: cout << "Enter" << std::endl;
//std:: cout << "Check::"<<
//TryEquals<std::function<void(int)>>::equals(f,f2) << std::endl;
A a1;
A a2;
std:: cout << "Check::"<< TryEquals<A>::equals(a1,a2) << std::endl;
return 0;
}
TryEquals<std::function<void(int)>>::equals(f,f2)
抛出异常,因为运算符 == 未实现但
TryEquals<A>::equals(a1,a2)
returns 1 因为 class A 有一个运算符 ==。
在这一点上,我需要帮助来理解 conv 和 test 是如何工作的。
此外
static constexpr bool value = decltype(test<T>(nullptr,
nullptr))::value
有效吗?
我对这个表达感到困惑
decltype(test<T>(nullptr,nullptr))::value.
不需要定义这些函数,因为它们实际上从未被调用过。
decltype
是 ,它计算出函数的 return type,但从不尝试计算 return 值.
在这种情况下它与sfinae组合在一起,这样如果decltype
无法找出==
的return类型(可能是因为运算符没有存在)test
的重载将被忽略。然后 test(...)
将被选中。
这利用了 ...
是参数类型的绝对最差匹配这一事实,因此只有在没有其他重载可用时才会使用它(因此 "fallback")。
顺便说一下,std::declval
也从未定义过。
阅读第二版 C++ 模板的第 22 章,我试图理解 EqualityComparable 特性的实现。但是我不明白编译器是如何决定是否激活回退的。
除此之外还有两个只声明但程序编译运行的函数。这对我来说很奇怪。
这是代码。 头文件IsEqualityComparable.hpp
#include <utility> // for declval()
#include <type_traits> // for true_type and false_type
template<typename T>
class IsEqualityComparable
{
private:
// test convertibility of == and ! == to bool:
static void* conv(bool); // to check convertibility to bool
template<typename U>
static std::true_type test(decltype(conv(std::declval<U const&>() ==
std::declval<U const&>())),
decltype(conv(!(std::declval<U const&>() ==
std::declval<U const&>())))
);
// fallback:
template<typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(nullptr,
nullptr))::value;
};
源文件如下
#include <iostream>
#include <exception>
#include <utility>
#include <functional>
#include "isequalitycomparable.hpp"
template<typename T,
bool EqComparable = IsEqualityComparable<T>::value>
struct TryEquals
{
static bool equals(T const& x1, T const& x2) {
std:: cout << "IsEqualityComparable equals::"<<std::endl;
return x1 == x2;
}
};
class NotEqualityComparable : public std::exception
{
};
template<typename T>
struct TryEquals<T, false>
{
static bool equals(T const& x1, T const& x2) {
std:: cout << "Throw::"<<std::endl;
throw NotEqualityComparable();
}
};
void foo(int)
{
}
void bar(int)
{
}
class A
{
public:
A() = default;
friend bool operator ==(A a1 , A a2)
{
return true;
}
};
int main()
{
std:: cout << "Enter" << std::endl;
std::function<void(int)> f = foo;
std::function<void(int)> f2 = f;
std:: cout << "Enter" << std::endl;
//std:: cout << "Check::"<<
//TryEquals<std::function<void(int)>>::equals(f,f2) << std::endl;
A a1;
A a2;
std:: cout << "Check::"<< TryEquals<A>::equals(a1,a2) << std::endl;
return 0;
}
TryEquals<std::function<void(int)>>::equals(f,f2)
抛出异常,因为运算符 == 未实现但
TryEquals<A>::equals(a1,a2)
returns 1 因为 class A 有一个运算符 ==。
在这一点上,我需要帮助来理解 conv 和 test 是如何工作的。
此外
static constexpr bool value = decltype(test<T>(nullptr,
nullptr))::value
有效吗?
我对这个表达感到困惑
decltype(test<T>(nullptr,nullptr))::value.
不需要定义这些函数,因为它们实际上从未被调用过。
decltype
是
在这种情况下它与sfinae组合在一起,这样如果decltype
无法找出==
的return类型(可能是因为运算符没有存在)test
的重载将被忽略。然后 test(...)
将被选中。
这利用了 ...
是参数类型的绝对最差匹配这一事实,因此只有在没有其他重载可用时才会使用它(因此 "fallback")。
顺便说一下,std::declval
也从未定义过。