Использование выражения fold для создания тривиального объекта

Я пытаюсь создать объект, используя выражения std::apply и fold. Из того, что я могу сказать, читая документацию в Интернете, сложение запятой должно работать. Вот пример для пояснения.

struct my_pair final {
    float x;
    float y;
};

struct test final {
    my_pair back() {
        return std::apply(
                [](auto&... vector) {
                    return my_pair{ (vector.back(), ...) }; },
                data);
    }

    std::tuple<std::vector<float>, std::vector<float>> data
            = { { 0.f }, { 1.f } };
};

Я распаковываю кортеж, получаю последние элементы и пытаюсь вернуть новый объект, используя элементы.

Различные компиляторы жалуются, что y никогда не инициализируется. Почему-то расширения не происходит. По крайней мере, не так, как я ожидал.

error: missing field
      'y' initializer [-Werror,-Wmissing-field-initializers]
  ...[](auto&... vector) { return my_pair{ (vector.back(), ...) }; },
                                                                ^

Если я отключу -Werror, первое значение my_pair равно 1, второе — 0. Я пытался использовать унарную складку влево, но результаты были идентичными.

Похоже, это должно работать, cppreference имеет этот пример вектора push_back, который выглядит похоже (с моей точки зрения).

template<typename T, typename... Args>
void push_back_vec(std::vector<T>& v, Args&&... args)
{
    (v.push_back(args), ...);
}

Можно ли создать объект тривиального типа (pod), используя выражения fold? Если да, то из распакованного кортежа?


person scx    schedule 10.03.2018    source источник
comment
Помните, что выражение сгиба по-прежнему является выражением. y инициализируется вторым выражением, и оно у вас есть.   -  person chris    schedule 10.03.2018


Ответы (1)


Вам не нужно выражение сгиба здесь. Правильный код:

[](auto&... vector) 
{
    return my_pair{vector.back()...}; 
}

С вашим существующим кодом происходит следующее расширение:

return my_pair{ (0.f, 1.f) }

Первый элемент при инициализации с (0.f, 1.f) оценивается как 1.f. В данном случае токен-запятая представляет собой оператор-запятую — он не разделяет аргументы во время агрегатной инициализации.

person Vittorio Romeo    schedule 10.03.2018
comment
Ха-ха круто, ти! Не ожидал такого простого решения :) - person scx; 10.03.2018