我怎样才能为我自己的 class 专门化一个标准概念?
How can I specialize a standard concept for my own class?
我有一个适用于所有整数类型的模板函数:
#include <concepts>
template<typename T>
bool odd(T n) requires std::integral<T>
{
return n & T(1);
}
现在我想将这个函数与一些用户定义的整数类型一起使用,例如boost::multiprecision::cpp_int
#include <boost/multiprecision/cpp_int.hpp>
boost::multiprecision::cpp_int n = ...
std::cout << odd(n) << std::endl;
gcc 10 给出
error: use of function ‘bool odd(T) requires integral<T> [with T = boost::multiprecision ...
这当然是正确的。我能做些什么来解决这个问题,即如何为我自己的类型专门化一个标准概念?
how can I specialize a standard concept for my own type?
你不知道。概念不能专门化。类型特征在某些情况下可以,但 std::integral
不是你可以做到的,所以这也不是正确的途径。
What can I do to fix this
您需要为正在使用的算法集提出正确的概念。显然最直白的是:
template <typename T>
concept IsOddable = std::constructible_from<T, int> &&
requires (T n) {
{ n & n } -> std::convertible_to<bool>;
};
但是不要那样做。您可能需要某种通用的 Numeric
概念并为 +
、*
、%
等添加任何要求。概念来自算法 - 所以找出通用的您的算法强加并从那里开始工作的要求。
好的,所以我添加了行
template< class T >
inline constexpr bool is_my_integral_v = false;
template<>
inline constexpr bool is_my_integral_v<boost::multiprecision::cpp_int> = true;
并将要求更改为
template<typename T>
bool odd(T n) requires std::integral<T> || is_my_integral_v<T>
现在可以使用了。
我有一个适用于所有整数类型的模板函数:
#include <concepts>
template<typename T>
bool odd(T n) requires std::integral<T>
{
return n & T(1);
}
现在我想将这个函数与一些用户定义的整数类型一起使用,例如boost::multiprecision::cpp_int
#include <boost/multiprecision/cpp_int.hpp>
boost::multiprecision::cpp_int n = ...
std::cout << odd(n) << std::endl;
gcc 10 给出
error: use of function ‘bool odd(T) requires integral<T> [with T = boost::multiprecision ...
这当然是正确的。我能做些什么来解决这个问题,即如何为我自己的类型专门化一个标准概念?
how can I specialize a standard concept for my own type?
你不知道。概念不能专门化。类型特征在某些情况下可以,但 std::integral
不是你可以做到的,所以这也不是正确的途径。
What can I do to fix this
您需要为正在使用的算法集提出正确的概念。显然最直白的是:
template <typename T>
concept IsOddable = std::constructible_from<T, int> &&
requires (T n) {
{ n & n } -> std::convertible_to<bool>;
};
但是不要那样做。您可能需要某种通用的 Numeric
概念并为 +
、*
、%
等添加任何要求。概念来自算法 - 所以找出通用的您的算法强加并从那里开始工作的要求。
好的,所以我添加了行
template< class T >
inline constexpr bool is_my_integral_v = false;
template<>
inline constexpr bool is_my_integral_v<boost::multiprecision::cpp_int> = true;
并将要求更改为
template<typename T>
bool odd(T n) requires std::integral<T> || is_my_integral_v<T>
现在可以使用了。