Я пытаюсь добавить элементы кортежа в вектор. Приведенный ниже код работает:
#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);
// ...
}
Но чтобы сделать код немного более читабельным, я попытался сделать следующее внутри лямбда-выражения в 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);
Приведенный выше код компилируется на g cc 9.2, но не компилируется на clang 9.0.0. Затем я попытался выяснить, почему: в соответствии с cppreference складные выражения pack
item должны быть выражением-выражением, в приведенном выше коде я передаю составное выражение, а не выражение-выражение. Если я сделаю это составное выражение лямбда-выражением, я смогу заставить его работать на 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);
Имея это в виду, могу ли я сказать, что в первом подходе к редактированию g cc неправильно разрешить компилировать код?