如何使用概念检查 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.
我正在尝试创建一个概念来检查是否有针对 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.