使用用户定义的类来计算某些类似的类模板

Calculate something with user defined classes by using variadic templates

本文关键字:用户 定义 计算      更新时间:2023-10-16

坐标;

   struct point{
       int x_, y_;
    }

假设我们具有上面定义的坐标。除了此结构外,我还想创建一个函数,该函数采用尽可能多的参数(例如,一个函数以找到三个或更多点的barycentre)。因此,我决定使用variadic模板。但是我认识到我缺乏有关变异模板的信息。

为了计算Barycentre,您应该添加所有X,将总和分为元素计数。并为y的元素做,然后返回点。您能带领我一种实施此操作的方法。

c 17的折叠表达使它变得轻而易举:

template <class... Points>
point barycentre(Points... points) {
    point const sum{
        (points.x_ + ...),
        (points.y_ + ...)
    };
    int const num = sizeof...(Points);
    return {
        sum.x_ / num,
        sum.y_ / num
    };
}

看到它活在Coliru

如果您使用的是C 14,则可以简单地通过constexpr函数中的点迭代,例如这样(例如,从昆汀的答案中借来的例子):

#include <iostream>
struct point{
    int x_, y_;
};
template <class... Points>
constexpr point barycentre(Points... points) {
    point ps[] = {points...};
    point result {0, 0};
    for (std::size_t i = 0; i < sizeof...(points); i++) {
        result.x_ += ps[i].x_;
        result.y_ += ps[i].y_;
    }
    result.x_ /= sizeof...(points);
    result.y_ /= sizeof...(points);
    return result;
}
int main() {
    constexpr auto bary = barycentre(point{0, 0}, point{2, 2});
    std::cout << "(" << bary.x_ << ", " << bary.y_ << ")n";
}

[live demo]


和一些C 11:

#include <iostream>
#include <array>
#include <type_traits>
struct point{
    int x_, y_;
};
template <std::size_t I, std::size_t N>
constexpr typename std::enable_if<I + 1 == N, point>::type barysum(std::array<point, N> const &points) {
    return point{ points[I].x_, points[I].y_ };
}
template <std::size_t I, std::size_t N>
constexpr typename std::enable_if<I + 1 != N, point>::type barysum(std::array<point, N> const &points) {
    return point{ points[I].x_ + barysum<I+1>(points).x_, points[I].y_ + barysum<I+1>(points).y_ };
}
template <std::size_t N>
constexpr point barycentre_impl(std::array<point, N> const points_array) {
    return point{ barysum<0>(points_array).x_ / static_cast<int>(N),  barysum<0>(points_array).y_ / static_cast<int>(N)};
}
template <class... Pts>
constexpr point barycentre(Pts... pts) {
    return barycentre_impl<sizeof...(Pts)>( {{pts...}} );
}
int main() {
    constexpr auto bary = barycentre(point{0, 0}, point{2, 2});
    std::cout << "(" << bary.x_ << ", " << bary.y_ << ")n";
}

[live demo]

初始化列表更简单地使用相同类型的元素。

Point average(std::initializer_list<Point> list)
{
    int x = 0, y = 0;
    for(auto &i: list) {x += i.x_; y += i.y_;}
    return {x / list.size(), y / list.size()};
}

variadic模板在 types 上是一般性的,因此它不适合您的情况。它不会使您的代码以任何方式更快地执行,只需膨胀二进制。