函数和继承中的非类型模板参数
Non-type template parameters in function and in inheritance
我正在学习 this 很棒的教程。作者大量使用可变参数模板,我陷入了困境,无法理解。你能帮帮我吗?
1.为什么不编译?
// this is simple
template<size_t I, typename T>
struct tuple_element
{
T value;
};
// this does NOT compiles: error: parameter pack 'Indices' must be at the end of the template parameter list
template <size_t... Indices, typename... Types>
struct tuple_impl : tuple_element<Indices, Types>...
{
};
接下来,作者有这段编译好的代码:
template <size_t... Indices>
struct index_sequence
{
using type = index_sequence<Indices...>;
};
template <typename Sequence, typename... Types>
struct tuple_impl;
template <size_t... Indices, typename... Types>
struct tuple_impl<index_sequence<Indices...>, Types...>
: tuple_element<Indices, Types>...
{
};
2。为什么在这种情况下一切正常? 我在这里看到几乎相同的模式:tuple_element<Indices, Types>...
3。为什么不能编译:
template <size_t... Indices>
void g(Indices...){}; //error: variable or field 'g' declared void
您看到的错误是在参数传递中。这是一个编译错误:
template <size_t... Indices, typename... Types>
struct tuple_impl
{};
规则是模板中不能有一个包后跟另一个包 class 模板参数列表。
第二个例子是一个专业化,其中包规则不存在。特化的模板参数仅仅是从针对主模板的模式匹配中提取的类型和值,按照类型名称后特化的 <>
部分的指导。
因为它们永远不会以相同的列表和顺序传入,所以一个 ...
一个接一个地出现不会造成任何歧义。对于主模板,顺序很重要,...
之后的任何内容都很难与 ...
的更多内容区分开来。可能是为了让编译器的工作更轻松,即使在它不能模棱两可的情况下(比如,一组文字后跟一组类型),C++ 禁止使用它。
编译器无法区分第一个序列何时结束和第二个序列何时开始 - 因此在可变参数模板中允许只有一个参数包,在最后。
tuple_impl<a, b, c, d, e, f> //is d still an index or already a type? what about e?
这是可行的,因为 tuple_impl
本身是一个模板,它本身只有一个参数包,即 Types...
。碰巧在这个专业化中,第一个参数也是一个模板,它也有一个参数包。因此,与一个模板有两个包相比,您有两个模板各有一个包,这没问题。
这与可变参数模板无关,即出于同样的原因,它也不适用于单个参数。事实是,由于 Indices...
不是类型而是值,因此您没有定义函数。如果它不是 void,编译器稍后就会有问题。考虑这个例子,它略有修改但本质上是一个类似的结构:
template <size_t I>
unsigned g(I)
{}
中间一行居中:编译器认为是变量定义,用I
初始化。因此,您的情况会出现错误,因为 void
类型的变量根本没有意义。然后我的编译器发出关于模板的警告,它认为 g
是一个模板变量,而那些是 C++1y 扩展。完成后,他意识到 ;
未完成变量定义,发出错误并退出...
只是补充一些重要的事情:这是一个测试片段:
int main( int argc, char** argv )
{
using i3 = index_sequence<1, 2, 3>;
tuple_impl<i3, int, double, char> tup;
return 0;
}
注意:此处您将此 i3
作为 "index pack" 传递。 "master template" 始终定义必须如何将参数传递给模板。 template<...>
语句 if set for specialization 没有定义任何东西,只是参数组合在内部可能在专业化内部传播,但它不是 public 接口的一部分。
例如,如果您尝试使用 <1, 2, 3, int, double, char>
作为参数规范(理论上与专业化的模板参数规范匹配),它将无法编译。
我正在学习 this 很棒的教程。作者大量使用可变参数模板,我陷入了困境,无法理解。你能帮帮我吗?
1.为什么不编译?
// this is simple
template<size_t I, typename T>
struct tuple_element
{
T value;
};
// this does NOT compiles: error: parameter pack 'Indices' must be at the end of the template parameter list
template <size_t... Indices, typename... Types>
struct tuple_impl : tuple_element<Indices, Types>...
{
};
接下来,作者有这段编译好的代码:
template <size_t... Indices>
struct index_sequence
{
using type = index_sequence<Indices...>;
};
template <typename Sequence, typename... Types>
struct tuple_impl;
template <size_t... Indices, typename... Types>
struct tuple_impl<index_sequence<Indices...>, Types...>
: tuple_element<Indices, Types>...
{
};
2。为什么在这种情况下一切正常? 我在这里看到几乎相同的模式:tuple_element<Indices, Types>...
3。为什么不能编译:
template <size_t... Indices>
void g(Indices...){}; //error: variable or field 'g' declared void
您看到的错误是在参数传递中。这是一个编译错误:
template <size_t... Indices, typename... Types>
struct tuple_impl
{};
规则是模板中不能有一个包后跟另一个包 class 模板参数列表。
第二个例子是一个专业化,其中包规则不存在。特化的模板参数仅仅是从针对主模板的模式匹配中提取的类型和值,按照类型名称后特化的 <>
部分的指导。
因为它们永远不会以相同的列表和顺序传入,所以一个 ...
一个接一个地出现不会造成任何歧义。对于主模板,顺序很重要,...
之后的任何内容都很难与 ...
的更多内容区分开来。可能是为了让编译器的工作更轻松,即使在它不能模棱两可的情况下(比如,一组文字后跟一组类型),C++ 禁止使用它。
编译器无法区分第一个序列何时结束和第二个序列何时开始 - 因此在可变参数模板中允许只有一个参数包,在最后。
tuple_impl<a, b, c, d, e, f> //is d still an index or already a type? what about e?
这是可行的,因为
tuple_impl
本身是一个模板,它本身只有一个参数包,即Types...
。碰巧在这个专业化中,第一个参数也是一个模板,它也有一个参数包。因此,与一个模板有两个包相比,您有两个模板各有一个包,这没问题。这与可变参数模板无关,即出于同样的原因,它也不适用于单个参数。事实是,由于
Indices...
不是类型而是值,因此您没有定义函数。如果它不是 void,编译器稍后就会有问题。考虑这个例子,它略有修改但本质上是一个类似的结构:template <size_t I> unsigned g(I) {}
中间一行居中:编译器认为是变量定义,用I
初始化。因此,您的情况会出现错误,因为 void
类型的变量根本没有意义。然后我的编译器发出关于模板的警告,它认为 g
是一个模板变量,而那些是 C++1y 扩展。完成后,他意识到 ;
未完成变量定义,发出错误并退出...
只是补充一些重要的事情:这是一个测试片段:
int main( int argc, char** argv )
{
using i3 = index_sequence<1, 2, 3>;
tuple_impl<i3, int, double, char> tup;
return 0;
}
注意:此处您将此 i3
作为 "index pack" 传递。 "master template" 始终定义必须如何将参数传递给模板。 template<...>
语句 if set for specialization 没有定义任何东西,只是参数组合在内部可能在专业化内部传播,但它不是 public 接口的一部分。
例如,如果您尝试使用 <1, 2, 3, int, double, char>
作为参数规范(理论上与专业化的模板参数规范匹配),它将无法编译。