如何在模板元编程中创建动态列表?
How do I create a dynamic list in template metaprogramming?
我一直在尝试模板元编程,但在制作动态列表时遇到了一些麻烦。我试过了
#include <iostream>
template<int I>
struct Int {
};
template<class _Value, class ..._Others>
struct List {
typedef _Value Value;
typedef List<_Others...> Next;
};
template<class _Value>
struct List<_Value, void> {
typedef _Value Value;
typedef void Next;
};
template<class _List>
void PrintList() {
std::cout << typename _List::Value::I << "\n";
PrintList<typename _List::Next>();
};
template<>
void PrintList<void>() {};
int main() {
PrintList<List<Int<1>, Int<2>, Int<3>>>();
}
但是我遇到了 2 个我无法弄清楚的编译错误。第一个是 std::cout << typename _List::Value::I << "\n";
上的 expected '(' before '<<' token
。我不知道如何打印出 int 值(我也试过 (typename _List::Value)::I
)。
第二个错误是我在 typedef List<_Others...> Next;
处的模板参数数量错误。不应该第一个参数上限为 Value
,其余的 Others
?
您不能使用 ::
语法访问模板参数。通常的约定是为类型添加 type
using
,为值添加 value
constexpr static
成员。
template<int I>
struct Int {
constexpr static auto value=I;
};
然后使用
std::cout << _List::Value::value << "\n";
。它不是一个类型,所以把 typename
放在那里也是不正确的。
第二个错误是因为你定义了 List
至少有一个参数,但你递归到 List<_Others...>
最后是空的。即使你想用 void
修复它,你忘记将它添加到列表中,试试 PrintList<List<Int<1>, Int<2>, Int<3>,void>>();
但是没有必要设置标记值,请参阅:
#include <iostream>
template<int I>
struct Int {
static constexpr auto value=I;
};
//Define List as naturally having any number of arguments, even zero.
template<class...Ts>
struct List{};
//Non-empty specialization.
template<class Head, class...Tail>
struct List<Head,Tail...>{
using head = Head;
using tail = List<Tail...>;
};
template<class _List>
void PrintList() {
std::cout << _List::head::value << "\n";
PrintList<typename _List::tail>();
};
//Printing empty list.
template<>
void PrintList<List<>>() {};
int main() {
PrintList<List<Int<1>, Int<2>, Int<3>>>();
}
在C++中使用using
更好,它们更易读并且可以模板化。
在 C++17 中你可以使用折叠表达式:
template<typename...Elements>
void fold_print(List<Elements...>){
((std::cout<<Elements::value<<'\n'),...);
}
int main() {
fold_print(List<Int<1>, Int<2>, Int<3>>{});
}
但是函数只能解包它们的参数,所以语法略有不同。或者它需要一个更多的 struct
包装器来解压它们。
我一直在尝试模板元编程,但在制作动态列表时遇到了一些麻烦。我试过了
#include <iostream>
template<int I>
struct Int {
};
template<class _Value, class ..._Others>
struct List {
typedef _Value Value;
typedef List<_Others...> Next;
};
template<class _Value>
struct List<_Value, void> {
typedef _Value Value;
typedef void Next;
};
template<class _List>
void PrintList() {
std::cout << typename _List::Value::I << "\n";
PrintList<typename _List::Next>();
};
template<>
void PrintList<void>() {};
int main() {
PrintList<List<Int<1>, Int<2>, Int<3>>>();
}
但是我遇到了 2 个我无法弄清楚的编译错误。第一个是 std::cout << typename _List::Value::I << "\n";
上的 expected '(' before '<<' token
。我不知道如何打印出 int 值(我也试过 (typename _List::Value)::I
)。
第二个错误是我在 typedef List<_Others...> Next;
处的模板参数数量错误。不应该第一个参数上限为 Value
,其余的 Others
?
您不能使用 ::
语法访问模板参数。通常的约定是为类型添加 type
using
,为值添加 value
constexpr static
成员。
template<int I>
struct Int {
constexpr static auto value=I;
};
然后使用
std::cout << _List::Value::value << "\n";
。它不是一个类型,所以把 typename
放在那里也是不正确的。
第二个错误是因为你定义了 List
至少有一个参数,但你递归到 List<_Others...>
最后是空的。即使你想用 void
修复它,你忘记将它添加到列表中,试试 PrintList<List<Int<1>, Int<2>, Int<3>,void>>();
但是没有必要设置标记值,请参阅:
#include <iostream>
template<int I>
struct Int {
static constexpr auto value=I;
};
//Define List as naturally having any number of arguments, even zero.
template<class...Ts>
struct List{};
//Non-empty specialization.
template<class Head, class...Tail>
struct List<Head,Tail...>{
using head = Head;
using tail = List<Tail...>;
};
template<class _List>
void PrintList() {
std::cout << _List::head::value << "\n";
PrintList<typename _List::tail>();
};
//Printing empty list.
template<>
void PrintList<List<>>() {};
int main() {
PrintList<List<Int<1>, Int<2>, Int<3>>>();
}
在C++中使用using
更好,它们更易读并且可以模板化。
在 C++17 中你可以使用折叠表达式:
template<typename...Elements>
void fold_print(List<Elements...>){
((std::cout<<Elements::value<<'\n'),...);
}
int main() {
fold_print(List<Int<1>, Int<2>, Int<3>>{});
}
但是函数只能解包它们的参数,所以语法略有不同。或者它需要一个更多的 struct
包装器来解压它们。