如何使用概念检查 std::less 是否有专业化?

How to check if there is a specialization for std::less, using concepts?

我正在尝试创建一个概念来检查是否有针对 std::less 的专业化。

cppreference 上看到 std::hash 的概念示例,我创建了以下代码:

#include <bit>
#include <complex>
#include <concepts>
#include <functional>
#include <iostream>
#include <type_traits>

template < typename DataType >
concept Lessable = requires(DataType value1, DataType value2)
{
    { std::less < DataType > {}(value1, value2) } -> std::convertible_to < bool >;
};

template < typename DataType >
concept Hashable = requires(DataType value)
{
    { std::hash < DataType > {}(value) } -> std::convertible_to < size_t >;
};

// Specialization for std::less < std::complex < float > >.
namespace std
{
    template <>
    struct less < std::complex < float > >
    {
        bool operator()(const std::complex < float > &number1, const std::complex < float > &number2) const
        {
            return number1.real() < number2.real() ||
                number1.real() == number2.real() && number1.imag() < number2.imag();
        }
    };
}

// Specialization for std::hash < std::complex < float > >.
namespace std
{
    template <>
    struct hash < std::complex < float > >
    {
        size_t operator()(const std::complex < float > &number1) const
        {
            return std::hash < float > {}(number1.real()) ^ std::rotl(std::hash < float > {}(number1.imag()), 1);
        }
    };
}

int main()
{
    std::cout << Lessable < std::complex < float > > << "\n";
    std::cout << Hashable < std::complex < float > > << "\n";

    return 0;
}

出于某种原因我不明白,如果存在专业化,Hashable 会按预期工作,返回 true;如果专业化不存在,则为 false。

但是 Lessable 始终 returns 为真,无论专业化是否存在。 谁能告诉我我做错了什么,我必须怎么做才能解决这个问题?

谢谢!

任何小于可比较的类型都可以与 std::less 进行比较。也就是说,主 std::less 模板将为给定的任何 T 调用 operator<。您 可以 为某些用户定义的类型提供显式特化,但如果您的类型 operator< 可比较,则不必这样做。

std::complex 本质上不小于可比性。但是,如果专门化的所有模板参数都是 本身 标准库类型,则不允许为标准库模板提供专门化。尝试这样做就达到了UB,所以你可以得到任何结果。

但无论如何,std::hash 是您必须 提供专业化的东西。这就是使类型“可散列”的部分含义。

这是针对不同类型功能的两种不同设计。类型可以隐式小于可比较,但类型不能隐式可哈希。

不,没有办法用概念来检测特定模板实例化是来自主模板还是特化。

如果您要做的是查看某个类型是否具有可比性,那么您根本不应该依赖 std::less。相反,您应该使用 std::totally_ordered concept.