C++ 计算模板递归嵌套深度
下面的顺序适用于对特定对象进行操作的递归 数据并行容器中的嵌套模板对象中的嵌套级别 班我从我可能使用的表达式模板引擎中取出 例如,想转置多维数据容器的一个索引吗 数组 我相信该准则在SFINAE下是明确的 容器转到函数的第三个匹配项,与嵌套级别不匹配。递归在函数的第二次出现时递归,直到嵌套级别匹配,并且递归在函数的第一次出现时终止C++ 计算模板递归嵌套深度,c++,templates,c++11,recursion,sfinae,C++,Templates,C++11,Recursion,Sfinae,下面的顺序适用于对特定对象进行操作的递归 数据并行容器中的嵌套模板对象中的嵌套级别 班我从我可能使用的表达式模板引擎中取出 例如,想转置多维数据容器的一个索引吗 数组 我相信该准则在SFINAE下是明确的 容器转到函数的第三个匹配项,与嵌套级别不匹配。递归在函数的第二次出现时递归,直到嵌套级别匹配,并且递归在函数的第一次出现时终止 #include <vector> #include <complex> #include <type_traits> #incl
#include <vector>
#include <complex>
#include <type_traits>
#include <iostream>
typedef std::complex<double> ComplexD;
template <class T> class TypeMapper {
public:
enum { NestLevel = T::NestLevel };
};
template<> class TypeMapper<ComplexD> {
public:
enum { NestLevel = 0 };
};
template<class obj> class Container {
public:
std::vector<obj> data;
Container(int size) : data (size){};
};
template<class obj> class Recursive {
public:
enum { NestLevel = TypeMapper<obj>::NestLevel + 1};
obj internal;
};
template<int N,class obj,typename std::enable_if<N==obj::NestLevel >::type * = nullptr > auto function(const obj &arg)-> obj
{
std::cout<<"Leaf "<<obj::NestLevel<<std::endl;
return arg;
}
template<int N,class obj,typename std::enable_if<N!=obj::NestLevel >::type * = nullptr > auto function(const obj &arg)-> obj
{
std::cout<<"Node "<<obj::NestLevel<<std::endl;
obj ret;
ret.internal=function<N>(arg.internal);
return ret;
}
template<int N,class obj> auto function(const Container<obj> & arg)-> Container<decltype(function<N>(arg.data[0]))>
{
Container<decltype(function<N>(arg.data[0]))> ret(arg.data.size());
for(int ss=0;ss<arg.data.size();ss++){
ret.data[ss] = function<N>(arg.data[ss]);
}
return ret;
}
int main(int argc,char **argv)
{
Container<Recursive<Recursive<ComplexD> > > array(10);
Container<Recursive<Recursive<ComplexD> > > ret(10);
ret = function<1>(array);
}
对于我期望的输出:
pab$ ./broken
Node 2
Leaf 1
Node 2
Leaf 1
Node 2
Leaf 1
Node 2
Leaf 1
Node 2
Leaf 1
Node 2
Leaf 1
Node 2
Leaf 1
Node 2
Leaf 1
Node 2
Leaf 1
Node 2
Leaf 1
然后
在容器上循环,调用
std::enable_if<N!=obj::NestLevel > function
这将递归,递减嵌套级枚举,然后在
std::enable_if<N==obj::NestLevel > function.
但是,GCC无法解析此函数,而是在无限递归循环4.8、4.9中调用functionContainer self,并出现内部编译器错误
在5.0上
匹配看起来有问题,因为functionconst容器和arg不应该
由于参数不匹配,可能会递归到自身。它应该这样做
替换失败并调用函数的其他模板。如果我重命名
并更改它编译的容器参数函数内的调用
模板是硬的,虽然-我的程序是合法的,这是一个编译器错误
更新:
#include <vector>
#include <complex>
#include <type_traits>
#include <iostream>
typedef std::complex<double> ComplexD;
template <class T> class TypeMapper {
public:
enum { NestLevel = T::NestLevel };
};
template<> class TypeMapper<ComplexD> {
public:
enum { NestLevel = 0 };
};
template<class obj> class Container {
public:
std::vector<obj> data;
Container(int size) : data (size){};
};
template<class obj> class Recursive {
public:
enum { NestLevel = TypeMapper<obj>::NestLevel + 1};
obj internal;
};
template<int N,class obj,typename std::enable_if<N==obj::NestLevel >::type * = nullptr > auto function(const obj &arg)-> obj
{
std::cout<<"Leaf "<<obj::NestLevel<<std::endl;
return arg;
}
template<int N,class obj,typename std::enable_if<N!=obj::NestLevel >::type * = nullptr > auto function(const obj &arg)-> obj
{
std::cout<<"Node "<<obj::NestLevel<<std::endl;
obj ret;
ret.internal=function<N>(arg.internal);
return ret;
}
template<int N,class obj> auto ffunction(const Container<obj> & arg)-> Container<decltype(function<N>(arg.data[0]))>
{
Container<decltype(function<N>(arg.data[0]))> ret(arg.data.size());
for(int ss=0;ss<arg.data.size();ss++){
ret.data[ss] = function<N>(arg.data[ss]);
}
return ret;
}
int main(int argc,char **argv)
{
Container<Recursive<Recursive<ComplexD> > > array(10);
Container<Recursive<Recursive<ComplexD> > > ret(10);
ret = ffunction<1>(array);
}
将函数重命名为ffunction可以消除前两次出现的第三次出现的歧义,然后G++生成正确的输出,因为它不会错误地递归回functioncontainer
似乎会影响g++的所有版本。ICEs在中,在4.9中工作。看起来像是5年的倒退。谢谢Columbo,我提交了这个,希望我能得到一些牵引力。但是我在4.9上没有成功。它错误地递归并命中了一个错误。cc:45:45:模板实例化深度超过了最大值900,该网站非常棒,谢谢。到目前为止,我一直在本地手动安装每个编译器版本。但是没有一个GCC版本编译过它,每个版本都有不同的错误。3.1版之后的所有Clang++版本均成功。已使用您的网站更新原始版本。
std::enable_if<N==obj::NestLevel > function.
pab$ g++-5 -std=c++11 broken.cc -o broken
'
Internal compiler error: Error reporting routines re-entered.
broken.cc: In substitution of 'template<int N, class obj> Container<decltype (function<N>(arg.data[0]))> function(const Container<obj>&) [with int N = 1; obj = <missing>]':
broken.cc:43:101: recursively required by substitution of 'template<int N, class obj> Container<decltype (function<N>(arg.data[0]))> function(const Container<obj>&) [with int N = 1; obj = <missing>]'
broken.cc:43:101: required by substitution of 'template<int N, class obj> Container<decltype (function<N>(arg.data[0]))> function(const Container<obj>&) [with int N = 1; obj = <missing>]'
broken.cc:45:33: Abort trap: 6
template<int N,class obj> auto function(const Container<obj> & arg)-> Container<decltype(function<N>(arg.data[0]))>
^
g++-5: internal compiler error: Abort trap: 6 (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://github.com/Homebrew/homebrew-versions/issues> for instructions.`enter code here`
#include <vector>
#include <complex>
#include <type_traits>
#include <iostream>
typedef std::complex<double> ComplexD;
template <class T> class TypeMapper {
public:
enum { NestLevel = T::NestLevel };
};
template<> class TypeMapper<ComplexD> {
public:
enum { NestLevel = 0 };
};
template<class obj> class Container {
public:
std::vector<obj> data;
Container(int size) : data (size){};
};
template<class obj> class Recursive {
public:
enum { NestLevel = TypeMapper<obj>::NestLevel + 1};
obj internal;
};
template<int N,class obj,typename std::enable_if<N==obj::NestLevel >::type * = nullptr > auto function(const obj &arg)-> obj
{
std::cout<<"Leaf "<<obj::NestLevel<<std::endl;
return arg;
}
template<int N,class obj,typename std::enable_if<N!=obj::NestLevel >::type * = nullptr > auto function(const obj &arg)-> obj
{
std::cout<<"Node "<<obj::NestLevel<<std::endl;
obj ret;
ret.internal=function<N>(arg.internal);
return ret;
}
template<int N,class obj> auto ffunction(const Container<obj> & arg)-> Container<decltype(function<N>(arg.data[0]))>
{
Container<decltype(function<N>(arg.data[0]))> ret(arg.data.size());
for(int ss=0;ss<arg.data.size();ss++){
ret.data[ss] = function<N>(arg.data[ss]);
}
return ret;
}
int main(int argc,char **argv)
{
Container<Recursive<Recursive<ComplexD> > > array(10);
Container<Recursive<Recursive<ComplexD> > > ret(10);
ret = ffunction<1>(array);
}