- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一个 MyCustomType
与 SomeOtherType
比较:
struct SomeOtherType {
int value;
constexpr bool operator==(const SomeOtherType& rhs) const = default;
};
struct MyCustomType {
int x;
constexpr bool operator==(const MyCustomType& rhs) const = default;
constexpr bool operator==(const SomeOtherType& rhs) const {
return x == rhs.value;
}
friend constexpr bool operator==(const SomeOtherType& lhs, const MyCustomType& rhs) {
return lhs.value == rhs.x;
}
};
这很棒,但是
static_assert(std::equality_comparable_with<MyCustomType, SomeOtherType>);
失败,这意味着我不能将它们用于
std::ranges
中的异构查找算法:
error: no type named 'type' in 'struct std::common_reference<const MyCustomType&, const SomeOtherType&>'
operator==
,但我们不满足通用引用要求(另请参阅
Does `equality_comparable_with` need to require `common_reference`? )。然而,实际上,我的类型是与
SomeOtherType
相当的平等。 .我如何说服编译器是这种情况?
最佳答案
在哲学上,std::equality_comparable_with
的共同引用要求显式编码编写异构时所做的隐式语句 operator==(T, U)
实际上意味着相等*:有一些常见的父类(super class)型“T
union U
”,其中 operator==
是平等。这个“T
union U
”实际上并不存在于 MyCustomType
的代码中和 SomeOtherType
.如果我们通过特化使类型真正存在 std::common_reference_t
,然后我们可以见面std::equality_comparable_with
.
*某些类型使用 operator==
用于等价而不是相等(例如迭代器+哨兵),因此不应该也不符合 std::equality_comparable_with
.
我们可以使用 std::basic_common_reference
用于指定代理引用的自定义点:
The class template
basic_common_reference
is a customization point that allows users to influence the result ofcommon_reference
for user-defined types (typically proxy references).
eq_proxy_ref<T>
其作用类似于 T
的引用. MyCustomType
必须隐式转换为 eq_proxy_ref<T>
. SomeOtherType
必须隐式转换为 eq_proxy_ref<T>
. basic_common_reference
的 MyCustomType
和 SomeOtherType
必须返回此 eq_proxy_ref<int>
.一个 eq_proxy_ref<MyCustomProxy>
如果您想避免泄漏 MyCustomType
的内部结构,也可以工作。 . eq_proxy_ref<T>
之间必须有比较运算符。 eq_proxy_ref<T>
必须服从要求的精神。 std::common_reference_t
不仅仅用于相等,包括
std::three_way_comparable_with
,
std::totally_ordered_with
,以及一些 Ranges 算法或 View 。因此,您的
eq_proxy_ref<T>
实际上应该是您的两种类型的通用引用,而不仅仅是实现平等的机制。
#include <concepts>
#include <type_traits>
// Assuming you don't own SomeOtherType:
template <typename T>
class MyCustomTypeEqProxy {
template <typename>
friend class MyCustomTypeEqProxy;
private:
T ref_;
public:
template <typename U>
requires std::convertible_to<U, T>
constexpr MyCustomTypeEqProxy(U ref)
: ref_(ref)
{}
constexpr MyCustomTypeEqProxy(const SomeOtherType& rhs)
requires std::convertible_to<const int&, T>
: ref_(rhs.value)
{}
template <typename U>
requires std::equality_comparable_with<T, U>
constexpr bool operator==(const MyCustomTypeEqProxy<U>& rhs) const {
return ref_ == rhs.ref_;
};
};
struct MyCustomType {
int x;
constexpr bool operator==(const MyCustomType& rhs) const = default;
constexpr bool operator==(const SomeOtherType& rhs) const {
return x == rhs.value;
}
friend constexpr bool operator==(const SomeOtherType& lhs, const MyCustomType& rhs) {
return lhs.value == rhs.x;
}
constexpr operator MyCustomTypeEqProxy<int>() const { return MyCustomTypeEqProxy<int>(x); }
};
namespace std {
// May not be needed, but allows the custom proxy reference to expand to common references
// of what we're comparing against.
template <typename T, typename U, template <typename> class TQ, template <typename> class UQ>
struct basic_common_reference<::MyCustomTypeEqProxy<T>, U, TQ, UQ> {
using type = ::MyCustomTypeEqProxy< std::common_reference_t<T, UQ<U>> >;
};
template <typename T, typename U, template <typename> class TQ, template <typename> class UQ>
struct basic_common_reference<T, ::MyCustomTypeEqProxy<U>, TQ, UQ> {
using type = ::MyCustomTypeEqProxy< std::common_reference_t<TQ<T>, U> >;
};
// Tell std::common_reference_t about MyCustomTypeEqProxy
template <template <typename> class LQ, template <typename> class RQ>
struct basic_common_reference<::MyCustomType, ::SomeOtherType, LQ, RQ> {
using type = ::MyCustomTypeEqProxy<int>;
};
template <template <typename> class LQ, template <typename> class RQ>
struct basic_common_reference<::SomeOtherType, ::MyCustomType, LQ, RQ> {
using type = ::MyCustomTypeEqProxy<int>;
};
}
Compiler Explorer link
std::equality_comparable_with
.
关于c++ - 我如何告诉编译器 MyCustomType 是quality_comparable_with SomeOtherType?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66944119/
我是一名优秀的程序员,十分优秀!