I'm trying to add tuple elements into a vector. The below code is working:
#include <iostream>
#include <vector>
#include <tuple>
#include <string>
#include <utility>
template<class ... T>
std::vector<void *> to_vector(std::tuple<T...> x) {
std::vector<void*> out;
out.reserve(sizeof...(T));
std::apply([&out](auto&&... args) {
(out.push_back(new std::remove_reference_t<decltype(args)>(std::forward<decltype(args)>(args))), ...);
}, x);
return out;
}
int main() {
std::tuple<int, double, std::string, int> x = {1, 3.14, "test", 9};
std::vector<void *> v = to_vector(x);
int i = 0;
std::apply([&](auto&&... args) {
((std::cout << *(std::remove_reference_t<decltype(args)>*)v[i++] << std::endl), ...);
}, x);
// ...
}
But in order to make the code a little bit more readable, I tried to do the following inside the lambda expression in std::apply
:
std::apply([&out](auto&&... args) {
(({
using elem_type = std::remove_reference_t<decltype(args)>;
out.push_back(new elem_type(std::forward<elem_type>(args)));
}), ...);
}, x);
The above code compiles on gcc 9.2, but does not compile on clang 9.0.0. Then, I tried to discover why: according to cppreference, fold expressions pack
item is expected to be an expression statement, in the above code, I'm passing a compound statement, not a expression statement. If I make this compound statement become a lambda expression, I can make it work on clang:
std::apply([&out](auto&&... args) {
([&](){
using elem_type = std::remove_reference_t<decltype(args)>;
out.push_back(new elem_type(std::forward<elem_type>(args)));
}(), ...);
}, x);
With that in mind, can I say that in the first edit approach that gcc is wrong to allow the code to compile?