Search code examples
c++constructortuplesc++17fold

Using fold expression to construct a trivial object


I am trying to construct an object using std::apply and fold expressions. From what I can tell reading documentation online, folding on the comma should work. Here is an example to clarify.

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

I unpack the tuple, get the last elements and try to return a new object using the elements.

Various compilers complain y is never initialized. Somehow expansion is not taking place. At least, not how I would expect.

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

If I disable -Werror, the first value of my_pair is 1, the second is 0. I tried using unary left fold, but the results where identical.

It seems like this should work, cppreference has this vector push_back example which looks similar (from my perspective).

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

Is it possible to create a trivial (pod) type object using fold expressions? If so, from an unpacked tuple?


Solution

  • You don't need a fold expression here. The correct code is:

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

    With your existing code, this is the expansion that occurs:

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

    The first element if being initialized with (0.f, 1.f), which evaluates to 1.f. In this case, the comma token is a comma operator - it is not separating the arguments during aggregate initialization.