Полностью ли поддерживаются выражения сгиба в VS2017? - PullRequest
0 голосов
/ 21 января 2019

Я нашел интересную статью и попробовал ее код в MSVS 2017:

#include <utility>
#include <tuple>

template <typename... Args, typename Func, std::size_t... Idx>
void for_each(const std::tuple<Args...>& t, Func&& f, std::index_sequence<Idx...>) {
    f(std::get<Idx>(t))...;
}

template <typename... Args, typename Func>
void for_each(const std::tuple<Args...>& t, Func&& f) {
    for_each(t, f, std::index_sequence_for<Args...>{});
}

template <typename T>
void Write(std::wostream & out, const T & t)
{
    out << t;
}

template<typename ...Args>
void WriteV(std::wostream & out, Args&... args)
{
    for_each(std::tuple<Args&...>(args...), [&out](auto& a) { Write(out, a); });
}

struct A
{
    int n;
    std::wstring s;
    double d;
};

    void main()
    {
        std::wostringstream out;

        A a{ 1, std::wstring(L"2"), 3.0 };
        WriteV(a.n, a.s, a.d);
    }

, но код не скомпилирован с ошибками:

error C2760: syntax error: unexpected token '...', expected ';'
error C3520: 'Idx': parameter pack must be expanded in this context

означает ли это, что VS2017 не полностью поддерживает выражения сгиба?

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Этот путь неправильный

f(std::get<Idx>(t))...;

Вы должны выбрать.

(1) Вы хотите вызвать f() только один раз со всеми аргументами? В этом случае вы должны поместить многоточие ("...") внутрь , звонок

f(std::get<Idx>(t)...);

(2) или вы хотите (я полагаю, так и есть в вашем примере) вызов f() с каждым аргументом (N аргумент, N вызовы)? В этом случае вы можете (начиная с C ++ 17) использовать свертывание шаблона с оператором запятой, добавив пару скобок

    (f(std::get<Idx>(t) , ...);
// .^...................^....^   <- comma and parentheses

Второй способ, до C ++ 17, может быть смоделирован внутри инициализации (обычно неиспользуемого) массива. Нечто следующее

using unused = int[];

(void) unused { 0, ((void)f(std::get<Idx>(t)), 0)... };
0 голосов
/ 21 января 2019

Для этого кода требуется всего несколько синтаксических исправлений:

(f(std::get<Idx>(t)), ...);

и

WriteV(out, a.n, a.s, a.d);

Обратите внимание, что этот код долго не нужен по какой-то причине. Его можно заменить просто

 template<typename ... Args>
 void WriteV(std::wostream & out, Args const & ... args)
 {
     (out << ... << args);
 }
...