C++20中浮点数连续范围的概念

huangapple go评论70阅读模式
英文:

Concept for floating-point contiguous range in C++20

问题

I'll provide translations of the code you provided, excluding the code itself. Here's the translated content:

I'm new to C++20 concepts and I'm struggling to define a concept for a floating-point contiguous range. I managed to write a concept that works more or less but I cannot use it to enforce a specific floating-point type such as `float` or `double`.

Here is my first attempt:

However, this concept also works when passing a `vector` of `double` values to the `add` function of the `C` class instead of causing a compilation error as shown below.

So in a second attempt I tried to use a parametrized concept instead. This indeed causes a compilation error for the `add` function of the `C` class if the floating-point type does not match. However, it breaks the `print` function.

With this approach, I get a compilation error when calling `c.add(w)` as expected. However, I also get a compilation error for `print(v)` and `print(w)` (template argument deduction/substitution failed).

You can find these two attempts here: 
.
To summarize, I'm stuck on the way to define a contiguous range of floating-point values that would both reject calls to `C::add` with the wrong floating-point type and accept calls to `print` for all floating-point types. So I would be grateful if anyone could help me to solve my issue.

If you have any specific questions or need further assistance, please feel free to ask.

英文:

I'm new to C++20 concepts and I'm struggling to define a concept for a floating-point contiguous range. I managed to write a concept that works more or less but I cannot use it to enforce a specific floating-point type such as float or double.

Here is my first attempt:

#include <concepts>
#include <iostream>
#include <ranges>
#include <vector>

template<class R>
concept FloatingPointRange = 
    std::ranges::contiguous_range<R> && 
    std::floating_point<std::ranges::range_value_t<R>>;

template<std::floating_point F>
class C {
  public:
    explicit C(F x) : x_{x} {}

    void add(FloatingPointRange auto const& r) {
        for (auto const& v : r) {
            x_ += v;
        }
    }
    
    F get() {
        return x_;
    }

  private:
    F x_;
};

void print(FloatingPointRange auto const& r) {
    for (const auto& v: r) {
        std::cout << v << "  ";
    }
    std::cout << "\n";
}

int main() {
    std::vector<float> v = {100, 100};

    C<float> c{10};
    std::cout << c.get() << "\n";  // This line prints "10".

    c.add(v);
    std::cout << c.get() << "\n"; // This line prints "210".

    print(v);  // This line prints "100 100".

    return 0;
}

However, this concept also works when passing a vector of double values to the add function of the C class instead of causing a compilation error as shown below.

std::vector<double> w = {1000, 1000, 1000, 1000};
c.add(w); // This works but I would like to get a compilation error because F = float here.

So in a second attempt I tried to use a parametrized concept instead. This indeed causes a compilation error for the add function of the C class if the floating-point type does not match. However, it breaks the print function.

#include <concepts>
#include <iostream>
#include <ranges>
#include <vector>

template<class R, class F>
concept FloatingPointRange = 
    std::ranges::contiguous_range<R> && 
    std::floating_point<F> &&
    std::same_as<std::ranges::range_value_t<R>, F>;

template<std::floating_point F>
class C {
  public:
    explicit C(F x) : x_{x} {}

    void add(FloatingPointRange<F> auto const& r) {
        for (auto const& v : r) {
            x_ += v;
        }
    }
    
    F get() {
        return x_;
    }

  private:
    F x_;
};

template<std::floating_point F>
void print(FloatingPointRange<F> auto const& r) {
    for (auto const& v: r) {
        std::cout << v << "  ";
    }
    std::cout << "\n";
}

int main() {
    std::vector<float> v = {100, 100};
    std::vector<double> w = {1000, 1000, 1000, 1000};

    C<float> c{10};
    std::cout << c.get() << "\n";  // This line prints "10"

    c.add(v);
    std::cout << c.get() << "\n";  // This line prints "210"

    c.add(w);  // This line causes a compilation error as expected.


    print(v);  // This line causes a compilation error.
    print(w);  // Same error as the previous line.

    return 0;
}

With this approach I get a compilation error when calling c.add(w) as expected. However, I also get a compilation error for print(v) and print(w) (template argument deduction/substitution failed).

You can find these two attempts here: https://godbolt.org/z/b8f4PvE3G (you can comment the #define GENERIC line at the beginning to switch between my two attempts).

To summarize, I'm stuck on the way to define a contiguous range of floating-point values that would both reject calls to C::add with the wrong floating-point type and accept calls to print for all floating-point types. So I would be grateful if anyone could help me to solve my issue.

答案1

得分: 1

你可以为 FloatingPointRange 概念定义一个默认的模板参数:

template<class R, class F = std::ranges::range_value_t<R>>
concept FloatingPointRange = 
    std::ranges::contiguous_range<R> && 
    std::floating_point<F> &&
    std::same_as<std::ranges::range_value_t<R>, F>;

并且可以使 print 仅对没有显式提供 F 参数的 FloatingPointRange 进行约束,这可以接受任何浮点数类型的范围:

void print(FloatingPointRange auto const& r) {
    for (auto const& v: r) {
        std::cout << v << "  ";
    }
    std::cout << "\n";
}

演示

英文:

You can define a default template parameter for the FloatingPointRange concept

template&lt;class R, class F = std::ranges::range_value_t&lt;R&gt;&gt;
concept FloatingPointRange = 
std::ranges::contiguous_range&lt;R&gt; &amp;&amp; 
std::floating_point&lt;F&gt; &amp;&amp;
std::same_as&lt;std::ranges::range_value_t&lt;R&gt;, F&gt;;

and make print only constrain the argument to be a FloatingPointRange for which F is not explicitly provided, which can accept any range of floating-point types:

void print(FloatingPointRange auto const&amp; r) {
for (auto const&amp; v: r) {
std::cout &lt;&lt; v &lt;&lt; &quot;  &quot;;
}
std::cout &lt;&lt; &quot;\n&quot;;
}

Demo

huangapple
  • 本文由 发表于 2023年3月15日 18:07:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75743218.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定