Как сделать конструктор с неизвестным количеством параметров? - PullRequest
0 голосов
/ 09 апреля 2020

Я пишу класс геометрии Полигон , который имеет закрытое поле std :: vector points где Point:

struct Point {
    double x,y;
}

Мне нужно построить полигон с неизвестным количеством точек с использованием шаблонов.

Я пытался

template<Point &head, Point &...tail>
Polygon() {
    this->points.push_back(head);
    Polygon(tail...);
}

Но при вызове Polygon polygon = Polygon(Point(1, 4), Point(14.5, -15), Point(0, 0.0)); происходит сбой с ошибкой

: нет подходящего конструктора для инициализации 'Polygon'

В чем проблема и как ее исправить? Я использую C ++ 14

Ответы [ 2 ]

7 голосов
/ 09 апреля 2020

Вы хотите:

struct Point {
    double x,y;
};

struct Polygon {
private:
    std::vector<Point> v;
public:
    template<class ... Points>
    Polygon(Points&& ... points) : v{std::forward<Points>(points)...} {}
};

все элементы пакета параметров расширены до вектор перегрузка конструктора, принимая список инициализатора.

и вызов ctor:

Polygon p = Polygon(Point{1,2},Point{2,3},Point{3,4});

EDIT

Как упомянул в комментарии NathanOliver, можно добавить некоторые SFINAE, чтобы обеспечить возможность вызова конструктора variadi c, только если все переданные аргументы являются экземплярами Point ,

template<
    class ... Points, 
    std::enable_if_t< std::conjunction_v< std::is_same<Point,std::decay_t<Points> >... > >* = nullptr 
>
Polygon(Points&& ... points) : v{std::forward<Points>(points)...} {}

Живая демоверсия

1 голос
/ 09 апреля 2020

Предыдущий ответ верен для вашего случая. Здесь более общий подход, при котором вы не можете просто «по совпадению» использовать векторный конструктор. Также полезно, если вы хотите выполнить любую другую операцию для каждого элемента.

class Polygon
{
public:

    Polygon() = default;

    template<typename ...Points>
    Polygon(Points&&... points)
    {
        add(std::forward<Points>(points)...);
    }

    template<typename ...Tail>
    Polygon& add(Point& main, Tail&&... tail)
    {
        add(main);
        add(std::forward<Tail>(tail)...);
        return *this;
    }

    Polygon& add(Point& main)
    {
        points.push_back(main);
        return *this;
    }

private:
    std::vector<Point> points;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...