维基百科(here)给出了for循环的编译时间... 我想知道我们可以使用类似的for循环与模板语句内... 例如......
是以下循环有效
template<int max_subdomain>
void Device<max_sudomain>::createSubDomains()
{
for(int i=0; i< max_subdomain; ++i)
{
SubDomain<i> tmp(member);
...
// some operations on tmp
...
}
}
SubDomain是一个接受模板参数int的类,这里使用的参数是Device类的成员。
谢谢你的回答...... 既然你知道我想要什么...... 无论如何,我实现了我想要的目标吗?
我终于得到了我想要的.............. 而不是直接使用for循环... 可以改为使用Boost::MPL for_each construct。我还没有实现它,但我猜这提供了一种方法来做我想要的......
我从另一个堆栈溢出问题here中得到了答案......然而同一问题的comment拒绝使用它,因为它会非常慢(当然对于大的循环)。但是..对于不大的循环我不认为应该有任何膨胀......我会尝试代码,让你知道结果....
中很好地说明了这种用法答案 0 :(得分:8)
有一个标准的解决方案。将迭代器转换为递归。
template<int i>
void Device::createSubDomains()
{
SubDomain<i> tmp(member);
// some operations on tmp
createSubDomains<i-1>();
}
template<>
void Device<-1>::createSubDomains()
{
// End of recursion.
}
注意:您不能使用运行时if(i!=0) createSubDomains<i-1>();
。
2017注意:您现在可以使用编译时if constexpr(i!=0) createSubDomains<i-1>();
答案 1 :(得分:2)
即使你已经接受了@iammilind的回答,让我提出另一个答案,因为他为什么i
不是编译时常量的推理是不正确的。< / p>
假设你有
template<unsigned int MAX> struct SubDomain {...};
...
并且您想要声明它的实例......
SubDomain<i> tmp(member);
然后i
必须是通常所谓的编译时常量。那是什么?
标准将术语nontype template argument
分配给非类型的模板参数(D'Oh)。
14.3.2 模板非类型参数 [temp.arg.nontype]
非类型非模板模板参数的模板参数应为以下之一:
- 整数或枚举类型的整数常量表达式;或
- ...... [更多关注,但不相关]
正确的第一点包含进一步研究的参考:an integral constant-expression
。这导致我们
5.19 常量表达式 [expr.const]
在一些地方,C ++需要表达式来计算整数或枚举常量:作为数组 bounds(8.3.4,5.3.4),作为case表达式(6.4.2),作为位字段长度(9.6),作为枚举器初始化器(7.2), as static member initializers(9.4.2), 以及整数或枚举非类型模板参数(14.3) 。
然后,关键是:
整数常量表达式只能包含文字(2.13),枚举数,常量变量或静态 使用常量表达式(8.5)初始化的整数或枚举类型的数据成员,非类型模板 整数或枚举类型的参数,以及表达式的大小。
如果我们回顾你的循环:
for (int i=...
...
SubDomain<i>
然后我们现在可以观察到那里不允许i
。为什么?因为i
不是const variable
。
观察读者现在可能认为你可以绕过这个:
for (int i=...
...
const int I = i;
SubDomain<I>
但是这真的允许吗?否定,I = i
不是整数常量表达式,因为i
不是。它有助于实现递归地应用整数常量表达式的规则。
例如,以下是有效代码:
template <int> void foo() {}
int main () {
const int ccI = 0;
const int ccJ = ccI*2;
const int ccK = ccJ/4;
foo<ccK>();
}
但是,如果只将链的一部分设为非常数,则ccK
不再被视为整数常量:
template <int> void foo() {}
int main () {
int ccI = 0;
const int ccJ = ccI*2; // not compile time constant
const int ccK = ccJ/4; // same
foo<ccK>(); // error
}
因此,在人类可读的形式中,非类型但是(整数)值的模板参数必须是编译时常量:
答案 2 :(得分:0)
<强>重新修改:
我之前的回答是正确的。我试过你的代码,它给出了编译器错误。你无法声明这样的对象,因为i
不能保持编译时常量(,因为你打算做 i++
)。 template
参数必须始终是编译时常量。这是the demo。
另请注意,作为编译器优化的一部分,循环展开也是针对正常循环完成的。它不仅限于template
s。