为什么这超过了递归模板的最大深度
Why does this exceed the maximum recursive template depth?
我一直在玩可变模板,并注意到以下内容。
这很好:
auto t = std::make_tuple(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
这将给出错误(gcc 4.8.2(编辑:Clang 3.4)默认情况下最大深度为256):
auto t2 = std::make_tuple(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);
但是,直接创建元组是可行的:
std::tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> t3(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);
我在尝试创建一个返回模板化类的模板化函数时注意到了这一点。
template <typename...Arguments>
struct Testing {
std::tuple<Arguments...> t;
Testing(Arguments...args) : t(args...) {}
};
template <typename... Arguments>
Testing<Arguments...> create(Arguments... args) {
return Testing<Arguments...>(args...);
}
在这种情况下,这将起作用:
auto t4 = create(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
而这不会:
auto t5 = create(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);
问题不是make_tuple
,而是libstdc++(gcc4.8.2)中tuple
的移动构造函数。
对于类模板,成员函数仅在使用时实例化。noexcept规范也有类似的延迟,例如参见CWG问题1330。
当从make_tuple
初始化变量时,move构造函数会被实例化,即使它被省略了(例如,检查它是否格式错误)。这就是为什么您会看到仅定义tuple
变量和使用make_tuple
之间的差异。
move构造函数有一个递归实现的条件noexcept
。因此,对于每个模板参数,都需要恒定数量的额外实例化。clang++在超过最大实例化深度时的错误输出摘录:(支撑自己,文本墙传入)
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:803:24:注意:在实例化'__test的默认参数时,此处需要std::_Tuple_impl&&>'static true_type __test(int);^~~~~~~~~~~/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:803:24:注意:将推导出的模板参数替换为函数模板'__test'[其中_Tp=std::_Tuple_impl,_Arg=std::_Tuple_impl&&,$2=]static true_type __test(int);^//usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:117:14:注意:在此处请求的模板类"std::__is_direct_constructible_impl,std::_Tuple_impl&&>"的实例化中:public条件::type^/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:818:14:注意:在此处请求的模板类"std::__and_>,std::___is_direct_constructible_impl,std:::_Tuple_impl&&>>"的实例化中:公共__和_,^//usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:896:14:注意:在此处请求的模板类"std::__is_direct_constructible_new_safe,std::_Tuple_impl&&>"的实例化中:public条件::value,^//usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:904:39:注意:在此处请求的模板类"std::__is_direct_constructible_new,std::_Tuple_impl&&>"的实例化中:public integral_content,此处请求std::_Tuple_impl&&>':公共__is_direct_constructible^//usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:956:39:注意:在此处请求的模板类"std::__is_constructible_impl,std::_Tuple_impl&&>"的实例化中:public integral_content,此处请求std::_Tuple_impl&&>':public条件::type^/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:1042:14:注意:在此处请求的模板类"std::__and_,std::_Tuple_impl&&>,std:"__is_nt_constructionble_impl,std:"_Tuple_idmpl&&>>的实例化中:公共__和_,^//usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:1073:14:注意:在此处请求的模板类"std::is_nothrow_constructible,std::_Tuple_impl&&>"的实例化中:public is_nothrow_constructible^//usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:1079:1079:14:注意:在此处请求的模板类"std::__is_nothrow_move_constructible_impl,false>"的实例化中:公共__is_nothrow_move_constructible_impl^//usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:117:14:注意:在此处请求的模板类"std::is_nothrow_move_constructible>"的实例化中:public条件::type^//usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/tuple:268:16:注意:在此处请求的模板类"std::__and_,std::is_nothrow_move_constructible>>"的实例化中无例外(__and_,^/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../include/c++/4.8/type_traits:802:24:注意:在此处请求的'_Tuple_impl'异常规范的实例化中=decltype(::new _Tp(declval()))>
我们可以在这里看到例如is_nothrow_move_constructible
在is_nothrow_constructible
方面的实现,它在__is_nt_constructible
等方面实现,用于15个实例化级别。这就像一个调用堆栈一样打印,所以您可以从底部开始执行实例化。
这意味着tuple
的每个模板参数都需要15个额外的实例化级别来进行此检查。除此之外,始终需要9个级别(恒定深度)。
因此,17个参数需要17*15+9==264的实例化深度。
相关文章:
- 使用 std::istream_iterator 时,它似乎跳过了空文件行 - 如果可能的话,如何避免这种情况?
- C++ For Loop在过程中被跳过了.如何解决?
- C++跳过了辛线
- 如何在我的代码中修复无穷循环?我认为它跳过了第二个CIN,因此它一直在循环
- QT Qtimeline跳过了第一个框架
- 输入后,我的程序似乎跳过了第一个IF语句,直接转到ELSE
- C RLE BMP压缩跳过了最后一个字节
- 提升单元测试似乎跳过了应执行的代码
- C 将数据读取到一个结构,但它跳过了我的一个获取线,使该元素空白
- 为什么我的程序跳过了一个步骤
- 当我采用测试用例数 = 1 时,我的程序终止.其他明智的是,它给出了正确的答案,但跳过了最后一个测试用例
- 为什么我的代码跳过了这个循环
- 请解释:在 for 循环之后跳过了行
- C++编译器似乎跳过了代码行
- 跳过了 int* 的琐碎分配
- GLSL交错似乎在3DTV上甚至跳过了行
- std::basic_regex<char32_t>,有人已经尝试过了吗?
- 我可以使用' == '来比较两个向量吗?我试过了,似乎工作正常。但我不知道它是否适用于更复杂的情况
- c++ cin.Getline似乎被跳过了
- 为什么while循环被跳过了