template <typename T>\nconcept HasEq = requires(T t) {\n { t == t } -> std::convertible_to<bool>;\n};\n\nstruct X {};\nstatic_assert(not HasEq<X>);\n//bool a = pair<X, X>{} == pair<X, X>{};\nstatic_assert(! HasEq<pair<X, X>>); // fails! SIGH\nRun Code Online (Sandbox Code Playgroud)\n我想它\xe2\x80\x99 足够简单,可以定义一个概念“T 支持==”。它\xe2\x80\x99很简单,可以定义一个不支持运算符==的类型\'X\'。这个概念似乎对此很有效。
\n但令人困惑的是,pair<X,X> 并不真正支持运算符==(因为它委托给不存在的X 运算符==)。
\n然而 HasEq<pair<X, X>> 返回错误的答案(它表示已经定义了operator==)。
\n这似乎是 std C++ 运算符 ==(pair,pair) 定义的错误,无条件定义运算符 ==,而不是在运算符 == 定义上使用 \'enable_if\' 或 \'requires\'。但我不太确定我能做些什么来使 HasEq 正常工作(所以首先要了解这是否确实是 std::pair 运算符== 定义中的缺陷)。
\nlew*_*wis 11
好吧,我可能已经找到了答案(感谢上面评论中的提示!),但这让我觉得我需要洗澡。
https://godbolt.org/z/3crzGdvP5
#include <concepts>
#include <utility>
using namespace std;
namespace PRIVATE_ {
template <typename T>
concept HasEqBasic = requires(T t) {
{ t == t } -> std::convertible_to<bool>;
};
template <typename T>
constexpr inline bool has_eq_v = HasEqBasic<T>;
template <typename T, typename U>
constexpr inline bool has_eq_v<std::pair<T, U>> = has_eq_v<T> and has_eq_v<U>;
template <typename... Ts>
constexpr inline bool has_eq_v<std::tuple<Ts...>> = (has_eq_v<Ts> and ...);
} // namespace PRIVATE_
template <typename T>
concept HasEq = PRIVATE_::has_eq_v<T>;
struct X {};
static_assert(not HasEq<X>);
static_assert(!HasEq<pair<X, X>>);
Run Code Online (Sandbox Code Playgroud)
经过一番修补后,我想出了这个。聪明的头脑会告诉我它可能出了什么问题:
template <typename T>
concept BasicHasEq = requires(T t) {
{ t == t } -> std::convertible_to <bool>;
};
template <typename T>
concept IsPair = requires (T t) {
t.first;
t.second;
};
template <typename T>
concept IsNonComparablePair = IsPair <T> &&
(!BasicHasEq <decltype (std::declval <T> ().first)> ||
!BasicHasEq <decltype (std::declval <T> ().second)>);
template <typename T>
concept IsContainer = requires (T t) {
typename T::value_type;
};
template <typename T>
concept IsNonCopyableContainer = IsContainer <T> && !BasicHasEq <typename T::value_type>;
template <typename T>
concept HasEq = BasicHasEq <T> && !IsNonComparablePair <T> && !IsNonCopyableContainer <T>;
Run Code Online (Sandbox Code Playgroud)
编辑后还可以处理容器类型。可能还需要做更多的工作来处理所有可能发生的情况。