Variadic模板参数总是必须是最后的?

Jon*_*Mee 2 c++ parameters templates variadic-templates

我是否总是必须在模板参数的末尾放置可变参数模板参数?

template <size_t begin = 0U, typename... Tp>
void foo(tuple<Tp...> t);
Run Code Online (Sandbox Code Playgroud)

例如,我得到了各种错误:

#include <functional>
#include <iostream>
#include <string>
#include <tuple>
using namespace std;

template <typename... Tp, size_t begin = 0U>
enable_if_t<begin == sizeof...(Tp), void> foo(tuple<Tp...>& t){
    cout << endl;
}

template <typename... Tp, size_t begin = 0U>
enable_if_t<begin < sizeof...(Tp), void> foo(tuple<Tp...>& t) {
    cout << get<begin>(t) << ' ';
    foo<Tp..., begin + 1>(t);
}

int main() {
    tuple<int, string, float> t = make_tuple(42, "Jonathan Mee", 13.13);

    foo(t);
}
Run Code Online (Sandbox Code Playgroud)

上运行的gcc 5.1给我:

prog.cpp:在实例化中std::enable_if_t<(begin < sizeof... (Tp)), void> foo(std::tuple<_Elements ...>&) [with Tp = {int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, float}; unsigned int begin = 0u; std::enable_if_t<(begin < sizeof... (Tp)), void> = void]:
prog.cpp:21:7:从这里需要
prog.cpp:15:23:错误:没有用于调用foo(std::tuple<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, float>&)
foo<Tp..., begin + 1>(t);

prog.cpp的匹配函数:8:43:注意:candidate:template<class ... Tp, unsigned int begin> std::enable_if_t<(begin == sizeof... (Tp)), void> foo(std::tuple<_Elements ...>&)
enable_if_t<begin == sizeof...(Tp), void> foo(tuple<Tp...>& t){

prog.cpp :8:43:注意:模板参数推断/替换失败:
prog.cpp:13:42:注意:candidate:template<class ... Tp, unsigned int begin> std::enable_if_t<(begin < sizeof... (Tp)), void> foo(std::tuple<_Elements ...>&)
enable_if_t<begin < sizeof...(Tp), void> foo(tuple<Tp...>& t) {

prog.cpp:13:42:注意:模板参数推断/替换失败:

将参数交换为:

template <size_t begin = 0U, typename... Tp>
void foo(tuple<Tp...> t);
Run Code Online (Sandbox Code Playgroud)

该程序运行正常:http://ideone.com/SozUbb

如果真的要求变量模板参数是最后一个,有人可以给我一个关于这些信息的来源吗?

Bar*_*rry 7

问题不在于模板声明.这很好:

template <typename... Tp, size_t begin = 0U>
void foo(tuple<Tp...> t);
Run Code Online (Sandbox Code Playgroud)

问题是这个电话:

foo<Tp..., begin + 1>(t);
Run Code Online (Sandbox Code Playgroud)

虽然您可以在参数包之后提供默认模板参数,但您无法在以后实际设置它.编译器无法知道包的结束位置以及包开始后的参数.

您应该将排序begin作为第一个参数翻转,默认:

template <size_t begin = 0U, typename... Tp>
void foo(tuple<Tp...> t);
Run Code Online (Sandbox Code Playgroud)

这样你的递归调用可以是:

foo<begin + 1>(t);
Run Code Online (Sandbox Code Playgroud)