Является ли g cc неправильным, позволяя компилировать код с составным оператором? - PullRequest
3 голосов
/ 04 марта 2020

Я пытаюсь добавить элементы кортежа в вектор. Приведенный ниже код работает:

#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 неправильно разрешить компилировать код?

...