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?
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.