以下序列适用于对特定操作进行递归的递归 嵌套在数据并行容器中的嵌套模板对象中的嵌套级别 类。我提出了一个表达模板引擎,我尽可能地使用它 例如,想要转置一个多维容器的索引 阵列。
我相信SFINAE下的代码是明确的;
容器转到第三次出现的功能,无法匹配" NestLevel"。 "递归"通过第二次出现的函数进行递归,直到Nest Level匹配,并且递归在第一次出现函数时终止。
#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);
}
适用于Intel 15,Clang ++多个版本,可提供我期望的功能。
pab$ icpc -std=c++11 broken.cc -o broken
pab$ clang++ -std=c++11 broken.cc -o broken
pab$ clang++ --version
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
pab$ icpc --version
icpc (ICC) 15.0.3 20150408
Copyright (C) 1985-2015 Intel Corporation. All rights reserved.
我希望输出:
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
然后
function(const Container<obj> & arg)
循环容器,调用
std::enable_if<N!=obj::NestLevel > function
这会递归,递减嵌套级别枚举,然后匹配
std::enable_if<N==obj::NestLevel > function.
但是,GCC无法解析此问题,而是在无限递归循环(4.8,4.9)中使用函数(Container)自调用并且内部编译器错误 在5.0。
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`
匹配看起来很麻烦,因为函数(const Container&amp; arg)不应该 因为参数不匹配而自行递归。应该改为 替换失败并调用另一个模板的功能。如果我重命名 这些并更改它编译的Container参数函数内的调用。
模板很难 - 我的程序是否合法,这是编译器错误?
更新:
#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);
}
这个重命名&#34;功能&#34;到&#34; ffunction&#34;消除前两次出现的第三次消歧,然后G ++产生正确的输出,因为它没有(错误地)递归到函数(容器)中。
似乎会影响所有版本的g ++。