简体   繁体   English

复杂浮点类型的 C++20 概念

[英]C++20 concept for complex floating point types

I am trying to learn concepts in C++20 and I have a class that represents a data sample.我正在尝试学习 C++20 中的概念,并且我有一个表示数据样本的类。 I want to restrict this class to accept only floating point types, or complex floating point types but I can't seem to figure out how to handle complex values with concepts.我想限制这个类只接受浮点类型或复杂的浮点类型,但我似乎无法弄清楚如何用概念处理复杂的值。

Without concepts this is simple, but it allows way too many other data types that I don't want to allow.没有概念这很简单,但它允许太多我不想允许的其他数据类型。

Example without concepts:没有概念的例子:

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;
}

With concepts I can easily restrict it to just take floating point values but then it doesn't work with complex values.有了概念,我可以轻松地将其限制为仅采用浮点值,但它不适用于复杂值。

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;
}

How can I create a concept to restrict the template to work with both real and complex floating point values?如何创建一个概念来限制模板同时使用实数和复数浮点值?

Here's one solution that uses a partial specialization to check if T is a specialization of std::complex for floating point types:这是一个使用部分特化来检查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 {};

With this, you can write the concept:有了这个,你可以写出这个概念:

template <typename T>
concept complex = std::floating_point<T> || is_complex<T>::value;

Here's a demo .这是一个演示

Here's code using a helper type trait class with partial specialization, to determine if a type is complex with floating point coordinates.这是使用具有部分特化的辅助类型特征类的代码,以确定类型是否为具有浮点坐标的复杂类型。

#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
{
    // ...
};

I used the remove_const_t because std::floating_point is satisfied by const float , etc., meaning your existing Sample (with constrained parameter) would allow Sample<const double> , etc. So the concept is defined to accept const std::complex<T> , making Sample<const std::complex<double>> etc. work.我使用remove_const_t是因为std::floating_point满足const float等,这意味着您现有的Sample (带有约束参数)将允许Sample<const double>等。所以这个概念被定义为接受const std::complex<T> ,使Sample<const std::complex<double>>等工作。 If that shouldn't be considered valid, you can remove the remove_const_t part and possibly consider also restricting your template to forbid cv-qualified types.如果这不应该被视为有效,您可以删除remove_const_t部分,并可能考虑限制您的模板以禁止 cv 限定类型。

[As @cigien noticed in their solution , the partial specialization of is_complex_floating_point is simpler to write using the std::floating_point concept. [正如@cigien 在他们的解决方案中注意到的那样, is_complex_floating_point的部分is_complex_floating_point使用std::floating_point概念更容易编写。 An exercise for the reader.供读者练习。 ;) ] ;)]

A little experimentation shows that you can do this:一个小实验表明你可以这样做:

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
{
    // ...
};

But it's not obvious how to avoid specialising std::complex in is_floating_point_or_complex (if indeed you want to).但是如何避免在is_floating_point_or_complex专门化std::complex (如果你确实想要的话)并不明显。

Live demo现场演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM