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

vwkv1x7d  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(134)

我是C++20概念的新手,我正在努力定义一个浮点连续范围的概念。我设法写了一个概念,或多或少地工作,但我不能用它来强制一个特定的浮点类型,如floatdouble
下面是我的第一次尝试:

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

但是,当将double值的vector传递给C类的add函数时,此概念也起作用,而不会导致编译错误,如下所示。

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.

所以在第二次尝试中,我尝试使用参数化概念,如果浮点类型不匹配,这确实会导致C类的add函数出现编译错误,但是它会破坏print函数。

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

使用这种方法,当我按预期调用c.add(w)时,我得到了一个编译错误。但是,我也得到了print(v)print(w)的编译错误(模板参数推导/替换失败)。
您可以在此处找到这两种尝试:https://godbolt.org/z/b8f4PvE3G(您可以在开头注解#define GENERIC行,以便在我的两次尝试之间切换)。
总而言之,我在定义一个连续的浮点值范围的过程中遇到了麻烦,这个范围既可以拒绝对带有错误浮点类型的C::add的调用,又可以接受对所有浮点类型的print的调用,所以如果有人能帮助我解决这个问题,我将不胜感激。

b4lqfgs4

b4lqfgs41#

可以为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>;

并且make print仅将参数约束为FloatingPointRangeF未显式提供,它可以接受任何范围的浮点类型:

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

Demo

相关问题