Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.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_Recursion_Sfinae - Fatal编程技术网

C++ 计算模板递归嵌套深度

C++ 计算模板递归嵌套深度,c++,templates,c++11,recursion,sfinae,C++,Templates,C++11,Recursion,Sfinae,下面的顺序适用于对特定对象进行操作的递归 数据并行容器中的嵌套模板对象中的嵌套级别 班我从我可能使用的表达式模板引擎中取出 例如,想转置多维数据容器的一个索引吗 数组 我相信该准则在SFINAE下是明确的 容器转到函数的第三个匹配项,与嵌套级别不匹配。递归在函数的第二次出现时递归,直到嵌套级别匹配,并且递归在函数的第一次出现时终止 #include <vector> #include <complex> #include <type_traits> #incl

下面的顺序适用于对特定对象进行操作的递归 数据并行容器中的嵌套模板对象中的嵌套级别 班我从我可能使用的表达式模板引擎中取出 例如,想转置多维数据容器的一个索引吗 数组

我相信该准则在SFINAE下是明确的

容器转到函数的第三个匹配项,与嵌套级别不匹配。递归在函数的第二次出现时递归,直到嵌套级别匹配,并且递归在函数的第一次出现时终止

#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);
}