VS2017 是否完全支持折叠表达式?
Are fold expressions fully supported in VS2017?
我找到了一个 interesting article 并使用 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不完全支持折叠表达式?
这段代码只需要几个语法修正:
(f(std::get<Idx>(t)), ...);
和
WriteV(out, a.n, a.s, a.d);
请注意,由于某些原因,此代码不必要太长。可以换成just
template<typename ... Args>
void WriteV(std::wostream & out, Args const & ... args)
{
(out << ... << args);
}
这种方式是错误的
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)... };
我找到了一个 interesting article 并使用 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不完全支持折叠表达式?
这段代码只需要几个语法修正:
(f(std::get<Idx>(t)), ...);
和
WriteV(out, a.n, a.s, a.d);
请注意,由于某些原因,此代码不必要太长。可以换成just
template<typename ... Args>
void WriteV(std::wostream & out, Args const & ... args)
{
(out << ... << args);
}
这种方式是错误的
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)... };