Пакет параметров не расширяется при перемещении кода из определения класса - PullRequest
0 голосов
/ 11 мая 2018

У меня есть шаблон класса, который выглядит так:

template<typename... Args>
class Foo
{
public:
    void Bar() {
        (std::get<Args>(m_args).Bar(), ...);
    }

private:
    std::tuple<Args...> m_args;
};

А вот как я его использую:

template<size_t I>
class Test
{
public:
    void Bar() {
        std::cout << I << std::endl;
    }
};

int main() {
    Foo<Test<0>, Test<1>> object;
    object.Bar();
}

Эта версия работает просто отлично, но мне нужно переместить определение метода из интерфейса класса (чтобы повысить его читабельность). Вопрос в том, каков синтаксис для этого трюка?

Я пробовал это:

template<typename... Args>
void Foo<Args...>::Bar() {
    (std::get<Args>(m_args).Bar(), ...);
}

, но компиляция завершается неудачно с сообщением об ошибке:

error C3520: 'Args': parameter pack must be expanded in this context
note: while compiling class template member function 'void Foo<Test<0>,Test<1>>::Bar(void)'
note: see reference to function template instantiation 'void Foo<Test<0>,Test<1>>::Bar(void)' being compiled
note: see reference to class template instantiation 'Foo<Test<0>,Test<1>>' being compiled
error C2228: left of '.Bar' must have class/struct/union
error C2059: syntax error: '...'

Я проверил этот код на clang 7, и он работает так, что он выглядит как ошибка компилятора MSC (visual studio 15.7.1).

Ошибка в сообществе разработчиков

1 Ответ

0 голосов
/ 11 мая 2018

Эта вещь выглядит как ошибка MSVC и воспроизводится при использовании выражений сворачивания.Таким образом, обходной путь - это понижение кода с C ++ 17 до C ++ 14 и использование «классического» * ​​1001 * hack:

template<typename... Args>
void Foo<Args...>::Bar() {
    (void)std::initializer_list<int>{
        (std::get<Args>(m_args).Bar(), 0)...
    };
}
...