复杂浮点类型的 C++20 概念
C++20 concept for complex floating point types
我正在尝试学习 C++20 中的概念,并且我有一个代表数据样本的 class。我想将此 class 限制为仅接受浮点类型或复杂的浮点类型,但我似乎无法弄清楚如何使用概念处理复杂的值。
没有概念这很简单,但它允许太多我不想允许的其他数据类型。
没有概念的例子:
template <typename T>
class Sample
{
// ...
};
int main()
{
// This compiles
Sample<double> s1;
Sample<complex<double>> s2;
// This also compiles (but I don't want it to!)
Sample<int> s3;
// This compiles as well (again, I don't want it to!)
Sample<complex<int>> s4;
}
有了概念,我可以很容易地将它限制为只接受浮点值,但它不适用于复杂的值。
template<floating_point T>
class Sample
{
// ...
};
int main()
{
// This compiles
Sample<double> s1;
Sample<float> s2;
// This does NOT compile (but I do want it to!)
Sample<complex<double>> s3;
}
我如何创建一个概念来限制模板同时处理实数和复数浮点值?
一点实验表明您可以这样做:
template <class T>
concept is_floating_point_or_complex = std::is_floating_point_v<T> || std::is_same_v <T, std::complex <double>>;
template<is_floating_point_or_complex T>
class Sample
{
// ...
};
但是如何避免在 is_floating_point_or_complex
中专门化 std::complex
并不明显(如果您确实想要)。
这是一个解决方案,它使用部分特化来检查 T
是否是 std::complex
对浮点类型的特化:
template <typename T>
struct is_complex : std::false_type {};
template <std::floating_point T>
struct is_complex<std::complex<T>> : std::true_type {};
有了这个,就可以写出概念了:
template <typename T>
concept complex = std::floating_point<T> || is_complex<T>::value;
这里是 demo。
这里的代码使用具有部分特化的辅助类型特征 class 来确定一个类型是否是具有浮点坐标的复杂类型。
#include <type_traits>
#include <concepts>
#include <complex>
template <typename T>
struct is_complex_floating_point : public std::false_type {};
template <typename T>
struct is_complex_floating_point<std::complex<T>>
: public std::bool_constant<std::is_floating_point_v<T>>
{};
template <typename T>
concept real_or_complex_floating_point =
std::floating_point<T> ||
is_complex_floating_point<std::remove_const_t<T>>::value;
template<real_or_complex_floating_point T>
class Sample
{
// ...
};
我使用 remove_const_t
因为 std::floating_point
被 const float
等满足,这意味着您现有的 Sample
(带有约束参数)将允许 Sample<const double>
,等等。所以这个概念被定义为接受const std::complex<T>
,使Sample<const std::complex<double>>
等工作。如果这不应该被认为是有效的,您可以删除 remove_const_t
部分并可能还考虑限制您的模板以禁止 cv-qualified 类型。
[正如@cigien 在 中注意到的那样,使用 std::floating_point
概念编写 is_complex_floating_point
的偏特化更简单。 reader 的练习。 ;)]
我正在尝试学习 C++20 中的概念,并且我有一个代表数据样本的 class。我想将此 class 限制为仅接受浮点类型或复杂的浮点类型,但我似乎无法弄清楚如何使用概念处理复杂的值。
没有概念这很简单,但它允许太多我不想允许的其他数据类型。
没有概念的例子:
template <typename T>
class Sample
{
// ...
};
int main()
{
// This compiles
Sample<double> s1;
Sample<complex<double>> s2;
// This also compiles (but I don't want it to!)
Sample<int> s3;
// This compiles as well (again, I don't want it to!)
Sample<complex<int>> s4;
}
有了概念,我可以很容易地将它限制为只接受浮点值,但它不适用于复杂的值。
template<floating_point T>
class Sample
{
// ...
};
int main()
{
// This compiles
Sample<double> s1;
Sample<float> s2;
// This does NOT compile (but I do want it to!)
Sample<complex<double>> s3;
}
我如何创建一个概念来限制模板同时处理实数和复数浮点值?
一点实验表明您可以这样做:
template <class T>
concept is_floating_point_or_complex = std::is_floating_point_v<T> || std::is_same_v <T, std::complex <double>>;
template<is_floating_point_or_complex T>
class Sample
{
// ...
};
但是如何避免在 is_floating_point_or_complex
中专门化 std::complex
并不明显(如果您确实想要)。
这是一个解决方案,它使用部分特化来检查 T
是否是 std::complex
对浮点类型的特化:
template <typename T>
struct is_complex : std::false_type {};
template <std::floating_point T>
struct is_complex<std::complex<T>> : std::true_type {};
有了这个,就可以写出概念了:
template <typename T>
concept complex = std::floating_point<T> || is_complex<T>::value;
这里是 demo。
这里的代码使用具有部分特化的辅助类型特征 class 来确定一个类型是否是具有浮点坐标的复杂类型。
#include <type_traits>
#include <concepts>
#include <complex>
template <typename T>
struct is_complex_floating_point : public std::false_type {};
template <typename T>
struct is_complex_floating_point<std::complex<T>>
: public std::bool_constant<std::is_floating_point_v<T>>
{};
template <typename T>
concept real_or_complex_floating_point =
std::floating_point<T> ||
is_complex_floating_point<std::remove_const_t<T>>::value;
template<real_or_complex_floating_point T>
class Sample
{
// ...
};
我使用 remove_const_t
因为 std::floating_point
被 const float
等满足,这意味着您现有的 Sample
(带有约束参数)将允许 Sample<const double>
,等等。所以这个概念被定义为接受const std::complex<T>
,使Sample<const std::complex<double>>
等工作。如果这不应该被认为是有效的,您可以删除 remove_const_t
部分并可能还考虑限制您的模板以禁止 cv-qualified 类型。
[正如@cigien 在 std::floating_point
概念编写 is_complex_floating_point
的偏特化更简单。 reader 的练习。 ;)]