处理参数包时什么时候需要省略号?
When is an ellipsis needed when dealing with parameter packs?
我正在努力理解 some code from cppreference.com。相关部分在这里
template<typename... Ts>
std::ostream& operator<<(std::ostream& os, std::tuple<Ts...> const& theTuple)
{
std::apply
(
[&os](Ts const&... tupleArgs)
{
os << '[';
std::size_t n{ 0 };
((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
os << ']';
}, theTuple
);
return os;
}
如果我对上面的解释正确 ((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...)
是逗号运算符上的折叠表达式。语义上是([some pattern involving the parameter pack's values] , ...)
,意思是用逗号折叠。
但是我不明白的是为什么sizeof
里面有一个sizeof...
?对我来说,省略号意味着扩展,但我们不想在那里扩展。 Ts
就像聚合类型,类似于元组,我们只需要在编译器评估折叠时该聚合类型在编译时的大小。事实上,在 Visual Studio 中,不管有没有省略号,它都可以工作。 Godbolt 告诉我,在 GCC 中也是如此。 (编辑:实际上我错了,没有它编译的省略号,但输出包含一个不应该存在的尾随逗号)
如果您想要参数包的大小,规则是始终使用 sizeof...
吗?
那里需要省略号,因为 sizeof...(Ts)
是 sizeof
的一种特殊形式,returns 是参数包的大小。普通 sizeof(Ts)
不能用于此目的,因为它需要保持在扩展模式中使用标准 sizeof
行为的可能性,即 sizeof(Ts)
returns 单个类型的大小计算折叠表达式。
我正在努力理解 some code from cppreference.com。相关部分在这里
template<typename... Ts>
std::ostream& operator<<(std::ostream& os, std::tuple<Ts...> const& theTuple)
{
std::apply
(
[&os](Ts const&... tupleArgs)
{
os << '[';
std::size_t n{ 0 };
((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
os << ']';
}, theTuple
);
return os;
}
如果我对上面的解释正确 ((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...)
是逗号运算符上的折叠表达式。语义上是([some pattern involving the parameter pack's values] , ...)
,意思是用逗号折叠。
但是我不明白的是为什么sizeof
里面有一个sizeof...
?对我来说,省略号意味着扩展,但我们不想在那里扩展。 Ts
就像聚合类型,类似于元组,我们只需要在编译器评估折叠时该聚合类型在编译时的大小。事实上,在 Visual Studio 中,不管有没有省略号,它都可以工作。 Godbolt 告诉我,在 GCC 中也是如此。 (编辑:实际上我错了,没有它编译的省略号,但输出包含一个不应该存在的尾随逗号)
如果您想要参数包的大小,规则是始终使用 sizeof...
吗?
那里需要省略号,因为 sizeof...(Ts)
是 sizeof
的一种特殊形式,returns 是参数包的大小。普通 sizeof(Ts)
不能用于此目的,因为它需要保持在扩展模式中使用标准 sizeof
行为的可能性,即 sizeof(Ts)
returns 单个类型的大小计算折叠表达式。