首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11变量模板:默认索引数组值

C++11变量模板:默认索引数组值
EN

Stack Overflow用户
提问于 2012-05-25 05:46:35
回答 3查看 1.1K关注 0票数 2

下面是一个使用来自Johannes Schaub - litbLuc Danton的答案的代码打印元组的简短程序。

代码语言:javascript
复制
#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 <int ...S, typename ...T>
void print(const std::tuple<T...> & tup, seq<S...> s) {
  int res[] = { (std::cout << std::get<S>(tup) << " ", 0)... };
  std::cout << std::endl;
}

int main() {
  std::tuple<double, int, char> tup(1.5, 100, 'c');
  print(tup, gens<std::tuple_size<decltype(tup)>::value >::type());
  return 0;
}

打印的第二个参数始终是gens<N>::type(),其中N是元组的大小。我试图通过提供一个默认参数来避免第二个要打印的参数:

代码语言:javascript
复制
template <int ...S, typename ...T>
void print(const std::tuple<T...> & tup, seq<S...> s = gens<std::tuple_size<decltype(tup)>::value >::type()) {
  int res[] = { (std::cout << std::get<S>(tup) << " ", 0)... };
  std::cout << std::endl;
}

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

tmp5.cpp:在函数‘void(const std::tuple<_Elements ...>&,seq)中,int ...S = {};T= {double,int,char}’:

tmp5.cpp:23:12:错误:嵌套名称说明符中使用的“std::tuple_size&>”类型不完整

您知道有什么方法可以在不使用第二个参数的情况下为像S... print**?**这样的函数提供吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-25 08:43:01

不,没有。

事实上,这个问题并不局限于变量模板,它发生在所有的模板函数中:参数的模板类型不能从其默认值中推导出来。

代码语言:javascript
复制
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'}
}

你得换个档次。

这样做的最简单方法是提供一个过载,负责传递第二个参数。毕竟,默认参数只是避免编写转发函数的语法糖。

票数 3
EN

Stack Overflow用户

发布于 2012-05-25 07:30:06

问题是,如果不提供第二个函数参数,编译器就无法推断索引序列S...。当它到达默认参数时,它需要知道S...是什么,所以它不能使用默认参数来确定它。

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

代码语言:javascript
复制
template <typename ...T>
void print(const std::tuple<T...> & tup) {
  print(tup,typename gens<sizeof...(T)>::type());
}
票数 3
EN

Stack Overflow用户

发布于 2012-05-25 07:23:23

也许有更好的方法,但我能想到的最简单的方法是增加一个额外的间接方向:

代码语言:javascript
复制
#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;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10749078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档