C++ C++;11可变模板:默认索引数组值

C++ C++;11可变模板:默认索引数组值,c++,c++11,tuples,variadic-templates,C++,C++11,Tuples,Variadic Templates,下面是一个简短的程序,使用从和的答案改编的代码打印元组 但是,结果是编译器错误: tmp5.cpp:在函数“void print(const std::tuple&,seq)[with int…S={};T={double,int,char}]中]: tmp5.cpp:23:12:错误:嵌套名称说明符中使用了不完整的类型“std::tuple_size&>” 您知道有什么方法可以提供S..而不使用第二个参数来实现像print这样的函数吗?可能有更好的方法,但我能想到的最简单的方法是添加一个额外的

下面是一个简短的程序,使用从和的答案改编的代码打印元组

但是,结果是编译器错误:

tmp5.cpp:在函数“void print(const std::tuple&,seq)[with int…S={};T={double,int,char}]中]:
tmp5.cpp:23:12:错误:嵌套名称说明符中使用了不完整的类型“std::tuple_size&>”


您知道有什么方法可以提供
S..
而不使用第二个参数来实现像
print
这样的函数吗?

可能有更好的方法,但我能想到的最简单的方法是添加一个额外的间接级别:

#include <iostream>
#include <tuple>

template<int ...>
struct seq { };

template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };

template<int ...S>
struct gens<0, S...> {
  typedef seq<S...> type;
};

template <typename ...T, int ...S>
void print_impl(const std::tuple<T...> & tup, seq<S...>) {
  int res[] = { (std::cout << std::get<S>(tup) << " ", 0)... };
  std::cout << std::endl;
}
// Pass args to real implementation here
template <typename ...T>
void print(const std::tuple<T...> & tup)
{
    print_impl(tup, typename gens<sizeof...(T)>::type());
}

int main() {
  std::tuple<double, int, char> tup(1.5, 100, 'c');
  print(tup);
  return 0;
}
#包括
#包括
模板
结构序列{};
模板
结构gens:gens{};
模板
结构族{
typedef-seq-type;
};
模板
无效打印(常量标准::元组和元组,顺序){

int res[]={(std::cout问题是,如果不提供第二个函数参数,编译器无法推断索引序列
S..
。当它到达默认参数时,它需要知道
S..
是什么,因此它无法使用默认参数来确定它

这可以通过提供一个重载
print
,用于构建索引列表并转发到接受索引列表的重载来解决:

template <typename ...T>
void print(const std::tuple<T...> & tup) {
  print(tup,typename gens<sizeof...(T)>::type());
}
模板
无效打印(常量标准::元组和元组){
打印(tup,typename gens::type());
}
不,没有

事实上,这个问题并不局限于可变模板,它适用于所有模板函数:参数的模板类型不能从其默认值推断

template <typename T>
void func(T = 0) {} // expected-note {candidate template ignored:\
                                      couldn't infer template argument 'T'}

int main() {
  func(); // expected-error {no matching function for call to 'func'}
}
模板
void func(T=0){}//预期注释{已忽略候选模板:\
无法推断模板参数“t”}
int main(){
func();//预期错误{调用'func'时没有匹配的函数}
}
你需要换个档位


最简单的方法是提供一个重载,用于传递第二个参数。毕竟,默认参数只是避免编写转发函数的语法糖。

我同意,但这与提供打印序列一样困难……我想知道是否有办法提供默认参数对于可变类型?我明白你的意思。但是有没有办法为可变模板指定默认参数?我将制作其中的几个函数,并希望使声明和调用它们尽可能简单…没有语法可以为可变参数提供默认参数。最好提供一个on或重载。铿锵风格的注释真的很无聊。@Johanneschaub litb:我必须承认,我非常喜欢这种显示编译错误的方式(当只有两个错误时…)。我使用的是异构元组(
tuple
),其内容都可以发送到模板函数
模板数组f(数组)
生成新的元组。我想现在,我将把序列设置为常量表达式,以避免第二个参数中重复的
gens
代码。
template <typename ...T>
void print(const std::tuple<T...> & tup) {
  print(tup,typename gens<sizeof...(T)>::type());
}
template <typename T>
void func(T = 0) {} // expected-note {candidate template ignored:\
                                      couldn't infer template argument 'T'}

int main() {
  func(); // expected-error {no matching function for call to 'func'}
}