当涉及参数包时,我可以依赖具有默认值的参数类型被推断为空包这一事实吗?

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++-6clang++-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);
}