【问题标题】:How to check if there is a specialization for std::less, using concepts?如何使用概念检查 std::less 是否有专门化?
【发布时间】:2021-03-07 19:28:53
【问题描述】:

我正在尝试创建一个概念来检查 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 总是返回true,无论是否存在特化。 谁能告诉我我做错了什么以及我必须做些什么来解决这个问题?

谢谢!

【问题讨论】:

  • 在std::complex 上进行测试应该归咎于timsong-cpp.github.io/cppwp/n4861/library#namespace.std-2 - 尝试自定义类型。
  • 如果你能在你的问题中解释为什么你想这样做 - 你希望通过这些知识实现什么 - 我们也许能够帮助你解决 那个问题以不同的方式。
  • 解释我想要达到的目标有点困难......但是,有了 Nicol Bolas 的回答,我想我可以用另一种方式解决我的问题。无论如何,感谢您的关注,凯西!

标签: c++ template-specialization c++-concepts


【解决方案1】:

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

std::complex 在本质上不亚于可比性。但是,如果专门化的所有模板参数都是它们自己 标准库类型,则不允许您为标准库模板提供专门化。尝试这样做可以实现 UB,因此您可以获得任何结果。

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

这是针对不同功能的两种不同设计。一个类型可以隐式地小于可比,但一个类型不能隐式地是可散列的。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 2012-09-08
    相关资源
    最近更新 更多