当涉及参数包时,我是否可以依赖具有默认值的参数类型被推断为空包



考虑一个例子:

#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选项编译的代码正常工作

是。您所依赖的,from [temp.arg.explicit]:

未以其他方式推导的尾随模板形参包(14.5.3)将被推导为一个空的模板实参序列。

什么构成"尾随模板参数包"实际上从来没有被正确定义过,但是这里所有的编译器都这样解释Is...


也就是说,我不会依赖它,不是因为它不正确,而是因为它使代码难以理解。特别是在这种情况下,有一种简单的方法可以提取lambda的所有元素:std::apply():
template <class... Ts>
void foo(std::tuple<Ts...> t) {
    std::apply([](auto&... args) {
        (std::cout << ... << args);
    }, t);
}

相关内容

最新更新