c++ - Variadic 模板参数总是必须放在最后吗?

标签 c++ templates parameters variadic-templates

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

template <size_t begin = 0U, typename... Tp>
void foo(tuple<Tp...> t);

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

#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 on gcc 5.1给我:

prog.cpp: In instantiation of 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: required from here
prog.cpp:15:23: error: no matching function for call to 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: note: 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: note: template argument deduction/substitution failed:
prog.cpp:13:42: note: 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: note: template argument deduction/substitution failed:

当参数交换为:

template <size_t begin = 0U, typename... Tp>
void foo(tuple<Tp...> t);

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

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

最佳答案

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

template <typename... Tp, size_t begin = 0U>
void foo(tuple<Tp...> t);

问题是这个调用:

foo<Tp..., begin + 1>(t);

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

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

template <size_t begin = 0U, typename... Tp>
void foo(tuple<Tp...> t);

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

foo<begin + 1>(t);

关于c++ - Variadic 模板参数总是必须放在最后吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35701888/

相关文章:

xml - 将 URL 参数添加到 Firefox 的 DuckDuckGo 搜索插件

c++ - std::polar 线程安全吗?

c++ - 使用 C++,使用 SFINAE 测试静态成员是否存在,返回错误值

c++ - 模板特化是否需要 template<> 语法?

c++ - 处理运行时类型未知的模板

java - 使用 Java String.split 方法从文本文件获取参数

c++ - 我们可以在类声明中声明类类型的指针吗?

c++ - 打包的结构没有预期的大小

javascript - 快速路由——路由到/secrets时出现404错误,我错过了什么

parameters - NSIS LogicLib 参数失败