Пакет параметров не расширяется при перемещении кода из определения класса

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

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

Решение

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

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]