为什么我不能手动提供模板参数?

时间:2012-05-30 21:55:46

标签: c++ gcc c++11 variadic-templates

我有一个可变参数模板函数f。这编译得很好(使用g++ -std=c++11并可能使用c++0x):

#include <tuple>

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

template <typename ...T, int ...S>
void f(std::tuple<T...> arg, seq<S...> s) {
  // ... do stuff
}

int main() {
  f<int>(std::tuple<int>(10), seq<0>());
  return 0;
}

编译器会自动填写有效的int ...S

但是,我似乎无法手动提供整数参数:

int main() {
  f<int, 0>(std::tuple<int>(10), seq<0>());
  return 0;
}

输出:

  

/tmp/t.cpp:在函数'int main()'中:/ tmp / t.cpp:12:42:错误:没有
  调用'f(std :: tuple,seq&lt; 0&gt;)'的匹配函数   /tmp/t.cpp:12:42:注意:候选人是:/tmp/t.cpp:7:6:注意:
  template void f(std :: tuple&lt; _TElements ...&gt;,
  seq)/tmp/t.cpp:7:6:注意:模板参数
  扣除/替换失败:

我相信我已经从技术上读到了应该只为模板函数提供一个可变参数模板参数包(在第一种情况下,它完全由上下文决定),因此解释它(?)。

对于调试,GCC中是否有办法将用于...S的扩展输出到stderrstdout?当他们最初没有编译时,调试这样的事情会非常有用。

1 个答案:

答案 0 :(得分:4)

我知道无法手动指定两个模板参数包。由于模板包可能包含任意多个参数,因此编译器无法知道您何时意味着第一个停止而第二个启动。然而,自动或部分自动演绎似乎有效,但我不确定这是否只是g ++的一些慷慨......

我不确定你究竟想做什么,但我打赌你不需要同时使用这两个模板包。您可以引入一层间接,例如,

template <typename ... Tuple_Elements>
void do_something_with_single_value(std::tuple<Tuple_Elements...> arg, int s) {
  // ... do stuff 
}

template <typename Tuple_Type, int ...S>
void f(Tuple_Type arg, seq<S...> s) {
  // ... do stuff which needs all S at the same time
  // ... call do_something_with_single_value in compile time loop to access tuple elements
}

也许您的签名暗示您的职能有太多责任。尝试创建功能明确的小功能。

有一种方法可以输出为T和S推导出的参数,但前提是编译器可以确定匹配。为此,您需要在编译时引发错误:

template <typename ...T, int ...S>
void f(std::tuple<T...> arg, seq<S...> s) {
static_assert(std::tuple_size<std::tuple<T...>>::value < 0, "Provoked error message");
    // ... do stuff
}

这将在您的工作示例中生成以下输出:

stack.cpp: In function ‘void f(std::tuple<_Elements ...>, seq<S ...>) [with T = {int}, int ...S = {0}]’:
stack.cpp:15:34:   instantiated from here
stack.cpp:10:2: error: static assertion failed: "Provoked error message"