当涉及参数包时,我可以依赖具有默认值的参数类型被推断为空包这一事实吗?
Can I rely on the fact the type of the parameter with a default value when involving parameter pack is deduced to an empty pack?
考虑一个例子:
#include <iostream>
#include <tuple>
#include <utility>
template <class... Ts, size_t... Is>
void foo(std::tuple<Ts...> t,
std::index_sequence<Is...> = {}) {
if (sizeof...(Ts) != sizeof...(Is)) {
foo(t, std::make_index_sequence<sizeof...(Ts)>{});
return;
}
(std::cout << ... << std::get<Is>(t));
}
int main() {
foo(std::make_tuple(1, 2, 3));
}
我假设函数 foo
的第二个参数的类型默认推导为 std::integral_sequence<std::size_t>
因此我不必创建辅助函数来使用 Is...
索引到元组元素,但可以调用 foo
并将第二个参数设置为 std::make_index_sequence<sizeof...(Ts)>{}
.
当涉及参数包时,我是否可以依赖具有默认值的参数类型被推断为空包,或者它可能导致未定义的行为?
以上使用 g++-6
和 clang++-3.6
使用 -std=c++1z
选项编译的代码按预期工作。
是的。你依赖,来自 [temp.arg.explicit]:
A trailing template parameter pack (14.5.3) not otherwise deduced will be deduced to an empty sequence of template arguments.
"trailing template parameter pack" 的构成实际上从来没有完全正确定义,但所有编译器在这里都这样解释 Is...
。
也就是说,我不会依赖它,不是因为它不正确,而是因为它使代码难以理解。特别是因为在这种情况下,有一种简单的方法可以提取 lambda 的所有元素:std::apply()
:
template <class... Ts>
void foo(std::tuple<Ts...> t) {
std::apply([](auto&... args) {
(std::cout << ... << args);
}, t);
}
考虑一个例子:
#include <iostream>
#include <tuple>
#include <utility>
template <class... Ts, size_t... Is>
void foo(std::tuple<Ts...> t,
std::index_sequence<Is...> = {}) {
if (sizeof...(Ts) != sizeof...(Is)) {
foo(t, std::make_index_sequence<sizeof...(Ts)>{});
return;
}
(std::cout << ... << std::get<Is>(t));
}
int main() {
foo(std::make_tuple(1, 2, 3));
}
我假设函数 foo
的第二个参数的类型默认推导为 std::integral_sequence<std::size_t>
因此我不必创建辅助函数来使用 Is...
索引到元组元素,但可以调用 foo
并将第二个参数设置为 std::make_index_sequence<sizeof...(Ts)>{}
.
当涉及参数包时,我是否可以依赖具有默认值的参数类型被推断为空包,或者它可能导致未定义的行为?
以上使用 g++-6
和 clang++-3.6
使用 -std=c++1z
选项编译的代码按预期工作。
是的。你依赖,来自 [temp.arg.explicit]:
A trailing template parameter pack (14.5.3) not otherwise deduced will be deduced to an empty sequence of template arguments.
"trailing template parameter pack" 的构成实际上从来没有完全正确定义,但所有编译器在这里都这样解释 Is...
。
也就是说,我不会依赖它,不是因为它不正确,而是因为它使代码难以理解。特别是因为在这种情况下,有一种简单的方法可以提取 lambda 的所有元素:std::apply()
:
template <class... Ts>
void foo(std::tuple<Ts...> t) {
std::apply([](auto&... args) {
(std::cout << ... << args);
}, t);
}