模板元编程:参数包中的模板参数数量错误
Template meta-programming: Wrong number of template arguments in Paramater Pack
我正在尝试使用 Template meta-programming 实现列表,但没有成功编译下一个代码:
#include <iostream>
template<int Value>
struct Int {
static constexpr int value = Value;
};
template<typename H, typename ...TT>
struct List {
typedef H head;
typedef List<TT...> next; // <-- Too few template arguments for class template 'List'
constexpr static int size = sizeof...(TT) + 1;
};
int main() {
typedef List<Int<1>, Int<2>, Int<3>> list1;
static_assert(list1::head::value == 1, "Failed"); // = Int<1>
static_assert(list1::size == 3, "Failed"); // = 3
typedef typename list1::next list1Tail; // = List<Int<2>, Int<3>>
static_assert(list1Tail::head::value == 2, "Failed");
static_assert(list1Tail::size == 2, "Failed"); // = 2
typedef typename list1Tail::next list2Tail; // = List<Int<3>> <<---error: wrong number of template arguments (0, should be at least 1)
static_assert(list2Tail::head::value == 3, "Failed");
static_assert(list2Tail::size == 1, "Failed");
std::cout << "Passed" << std::endl;
}
出现错误:
In instantiation of ‘struct List<Int<3> >’: error: wrong number of template arguments (0, should be at least 1)
我知道在我的情况下 List
必须处理两种类型 H
和 ...TT
,但是:
- 为什么调用
List<TT...>
还不够?
- 我该如何解决?
- 在这种情况下编译代码的最佳方法是什么?
在最后一步 List<TT...>
将实例化您的代码中未定义的特化 List<>
。你也应该写一个 "terminating" 专业:
template<typename H>
struct List<H> {
typedef H head;
typedef void next;
constexpr static int size = 1;
};
为一个元素提供专门化,这样您就不会尝试用空包实例化 List
。
template <class H>
struct List<H>
{
typedef H head;
constexpr static int size = 1;
};
您需要对空列表或包含单个元素的列表进行专门化。一种可能是首先声明一个完全可变的模板,然后创建两个特化:
template <typename...>
struct List;
template <typename H, typename... TT>
struct List<H, TT...> {
using head = H;
using next = List<TT... >;
constexpr static int size = sizeof... (TT) + 1;
};
template <>
struct List<> {
constexpr static int size = 0;
};
这样您就可以得到一个空列表 List<>
,而您当前的版本无法得到该列表。
Holt 解决方案的变体:递归的基本情况可以是主模板,而不是二次特化
template <typename...>
struct List
{ constexpr static int size = 0; };
template<typename H, typename ...TT>
struct List<H, TT...> {
using head = H;
using next = typedef List<TT...>;
constexpr static int size = sizeof...(TT) + 1;
};
遗憾的是可读性较差。
我正在尝试使用 Template meta-programming 实现列表,但没有成功编译下一个代码:
#include <iostream>
template<int Value>
struct Int {
static constexpr int value = Value;
};
template<typename H, typename ...TT>
struct List {
typedef H head;
typedef List<TT...> next; // <-- Too few template arguments for class template 'List'
constexpr static int size = sizeof...(TT) + 1;
};
int main() {
typedef List<Int<1>, Int<2>, Int<3>> list1;
static_assert(list1::head::value == 1, "Failed"); // = Int<1>
static_assert(list1::size == 3, "Failed"); // = 3
typedef typename list1::next list1Tail; // = List<Int<2>, Int<3>>
static_assert(list1Tail::head::value == 2, "Failed");
static_assert(list1Tail::size == 2, "Failed"); // = 2
typedef typename list1Tail::next list2Tail; // = List<Int<3>> <<---error: wrong number of template arguments (0, should be at least 1)
static_assert(list2Tail::head::value == 3, "Failed");
static_assert(list2Tail::size == 1, "Failed");
std::cout << "Passed" << std::endl;
}
出现错误:
In instantiation of ‘struct List<Int<3> >’: error: wrong number of template arguments (0, should be at least 1)
我知道在我的情况下 List
必须处理两种类型 H
和 ...TT
,但是:
- 为什么调用
List<TT...>
还不够? - 我该如何解决?
- 在这种情况下编译代码的最佳方法是什么?
在最后一步 List<TT...>
将实例化您的代码中未定义的特化 List<>
。你也应该写一个 "terminating" 专业:
template<typename H>
struct List<H> {
typedef H head;
typedef void next;
constexpr static int size = 1;
};
为一个元素提供专门化,这样您就不会尝试用空包实例化 List
。
template <class H>
struct List<H>
{
typedef H head;
constexpr static int size = 1;
};
您需要对空列表或包含单个元素的列表进行专门化。一种可能是首先声明一个完全可变的模板,然后创建两个特化:
template <typename...>
struct List;
template <typename H, typename... TT>
struct List<H, TT...> {
using head = H;
using next = List<TT... >;
constexpr static int size = sizeof... (TT) + 1;
};
template <>
struct List<> {
constexpr static int size = 0;
};
这样您就可以得到一个空列表 List<>
,而您当前的版本无法得到该列表。
Holt 解决方案的变体:递归的基本情况可以是主模板,而不是二次特化
template <typename...>
struct List
{ constexpr static int size = 0; };
template<typename H, typename ...TT>
struct List<H, TT...> {
using head = H;
using next = typedef List<TT...>;
constexpr static int size = sizeof...(TT) + 1;
};
遗憾的是可读性较差。