Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么这会超过最大递归模板深度?_C++_Templates_C++11_Variadic Templates - Fatal编程技术网

C++ 为什么这会超过最大递归模板深度?

C++ 为什么这会超过最大递归模板深度?,c++,templates,c++11,variadic-templates,C++,Templates,C++11,Variadic Templates,我一直在玩可变模板,并注意到以下几点 这很好: 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): 但是,直接创建元组将起作用: std::tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> t3(1,2,3,4

我一直在玩可变模板,并注意到以下几点

这很好:

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):

但是,直接创建元组将起作用:

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);
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规范也同样延迟,参见例如

make_tuple
初始化变量时,移动构造函数将被实例化,即使它被省略(例如,检查它是否格式错误)。这就是为什么只定义
tuple
变量和使用
make\u tuple
之间存在差异

move构造函数有一个递归实现的条件
noexcept
。因此,对于每个模板参数,需要固定数量的附加实例化。当超过最大实例化深度时,clang++错误输出的一段摘录:(支撑自己,输入文本的墙)

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:803:24:注意:在实例化“u test,std::_Tuple_impl&>”的默认参数时,此处需要 静态真实类型测试(int); ^~~~~~~~~~~ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:803:24:注意:将推导出的模板参数替换为函数模板“u test”[带Tp=std:Tuple_impl,Arg=std:Tuple_impl&,$2=] 静态真实类型测试(int); ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:117:14:注意:在模板类“std::_是可直接构造的”的实例化中,std:_Tuple_impl&>,此处请求 :公共条件::类型 ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../include/c++/4.8/type_traits:818:14:注意:在模板类“std::u和>”的实例化中,std:u是直接可构造的impl,std:Tuple&>' :public和, ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:896:14:注意:在模板类的实例化中,此处请求“std::_是可直接构造的_new_safe,std:_Tuple(Tuple)impl&>” :公共条件::值, ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:904:39:注意:在模板类的实例化中,这里请求“std::_是直接的可构造的,std:_Tuple_impl&>” :公共积分常数,标准::_Tuple_impl&&>,此处请求 :public\uuu可直接\u构造 ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:956:39:注意:在模板类的实例化中,此处请求“std::_是可构造的_impl,std:_Tuple_impl&>” :公共积分常数,标准::_Tuple_impl&&>,此处请求 :公共条件::类型 ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../include/c++/4.8/type_traits:1042:14:注意:在模板类的实例化中,这里请求“std::_Tuple_impl&>,std:_是可构造的,std:_Tuple_impl&>” :public和, ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:1073:14:注意:在模板类“std::is_nothrow_可构造”的实例化中,此处请求std:_Tuple\u impl&> :public是不可构造的 ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:1079:14:注意:在模板类的实例化中,此处请求“std::u是_nothrow_move_constructible_impl,false>” :public \uuuu是\uu notrow\u move\u constructible\u impl ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:117:14:注意:在模板类的实例化中,此处请求了“std::nothrow_move_constructible>” :公共条件::类型 ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../../include/c++/4.8/tuple:268:16:注意:在模板类“std::u和u”的实例化中,std::此处是否请求了nothrow\u move\u constructible>> 无例外(uu和u, ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../../../../include/c++/4.8/type_traits:802:24:注意:在这里请求的“\u Tuple\u impl”异常规范的实例化中 =decltype(::new_Tp(declval())> 我们可以在这里看到实现,例如,
is_nothrow\u move\u constructible
is_nothrow\u constructible
方面的实现,它是根据
\u is\u nt\u constructible
等实现的,用于15个实例化级别。这像调用堆栈一样打印,因此您可以从底部开始跟踪实例化


这意味着
tuple
的每个模板参数需要15个额外的实例化级别来进行此检查。除此之外,始终需要9个级别(恒定深度)


因此,17个参数需要17*15+9==264的实例化深度。

可能是因为
create
是一个“递归模板”,当您给它17个参数时,它需要17个深度,当您给它16个参数时,它需要16个深度,限制是(显然)16.g++4.8.2需要一个231的实例化深度来编译17个参数的
make\u tuple
make\u tuple
本身只增加了一个实例化深度,据我所见,问题可能是
tuple
本身。ooooh,这解释了我的困惑,他们肯定应该为我制作一些模板塔玛吉无recursive@user3586046
noexcept
检查是针对移动构造函数的,因此,即使C++11建议最大实例化深度至少为1024,g++的默认最大深度为900。请参阅
-ftemplate depthauto 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);
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:803:24: note: in instantiation of default argument for '__test, std::_Tuple_impl &&>' required here static true_type __test(int); ^~~~~~~~~~~ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:803:24: note: while substituting deduced template arguments into function template '__test' [with _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: note: in instantiation of template class 'std::__is_direct_constructible_impl, std::_Tuple_impl &&>' requested here : public conditional::type ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:818:14: note: in instantiation of template class 'std::__and_ >, std::__is_direct_constructible_impl, std::_Tuple_impl &&> >' requested here : public __and_, ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:896:14: note: in instantiation of template class 'std::__is_direct_constructible_new_safe, std::_Tuple_impl &&>' requested here : public conditional::value, ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:904:39: note: in instantiation of template class 'std::__is_direct_constructible_new, std::_Tuple_impl &&>' requested here : public integral_constant, std::_Tuple_impl &&>' requested here : public __is_direct_constructible ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:956:39: note: in instantiation of template class 'std::__is_constructible_impl, std::_Tuple_impl &&>' requested here : public integral_constant, std::_Tuple_impl &&>' requested here : public conditional::type ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:1042:14: note: in instantiation of template class 'std::__and_, std::_Tuple_impl &&>, std::__is_nt_constructible_impl, std::_Tuple_impl &&> >' requested here : public __and_, ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:1073:14: note: in instantiation of template class 'std::is_nothrow_constructible, std::_Tuple_impl &&>' requested here : public is_nothrow_constructible ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:1079:14: note: in instantiation of template class 'std::__is_nothrow_move_constructible_impl, false>' requested here : public __is_nothrow_move_constructible_impl ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:117:14: note: in instantiation of template class 'std::is_nothrow_move_constructible >' requested here : public conditional::type ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/tuple:268:16: note: in instantiation of template class 'std::__and_, std::is_nothrow_move_constructible > >' requested here noexcept(__and_, ^ /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:802:24: note: in instantiation of exception specification for '_Tuple_impl' requested here = decltype(::new _Tp(declval()))>