2012-07-01 66 views
2

我在读一篇关于非类型模板参数的文章,它说:

当被实例化时,只能传递编译时常量整数。这意味着100100+991<<3等被允许,因为它们是编译时间常量表达式。涉及函数调用的参数(例如abs(-120))是不允许的。

非类型模板参数

例子:

template<class T, int SIZE> 
class Array{}; 

int main(){ 
Array<int, 100+99> my_array; // allowed 
Array<int, abs(-120)> my_array; // not allowed 
} 

什么是100 + 99和ABS(-120)之间的区别?
如何编译100 + 99时间和abs(-120)不是?

+0

我高度怀疑整数字面量是否被视为一个对象。如果是的话,我很好奇C是如何做到这一点的,在那里没有运算符重载的概念。 – Mahesh

+0

如果C++是纯粹的面向对象语言,是的。但事实并非如此。继续尝试'100.operator +(99)',看看会发生什么。 –

+0

选择什么表达式可以在编译时进行有意义的评估在某些时候必定是任意的。 C++选择对此保守,所以它大多是微不足道的表达式,模板或其他所知道的“安全”。例如。编译器如何知道在编译时评估'printf(“”)'是否合理? – millimoose

回答

3

100+99在编译时优化为199

abs()是功能,它可能会或可能不会被标记constexpr(C++ 11的功能,这将允许你这样做,你可以轻松地检查cppreference或标准,看它是否是constexpr在C++ 11)。它需要被执行;编译器不能推断出它是状态较少的函数,对于每个具有相同参数的运行返回相同的值。

+1

如果标准'abs'没有标记为'constexpr',则可以编写自己的'abs',它可以是'constexpr'。 – Puppy

+0

显然在libstdC++中有一个constexpr abs,我可以使用'std :: abs(-120)'作为gcc 4.6中的非类型模板参数。 – mfontanini

+0

@mfontanini,因此我的“可能会或可能不会被标记”;我不知道标准是否保证。 – Griwes

4

无,而abs(-120)在C++ 11中完全合法。正如您充分指出的那样,C++ 03并没有在编译时可以评估的函数的范围,但是C++ 11确实可以。直接使用abs,您可以用执行相同计算的模板替换它,并在C++ 03中使用abs_template<-120>::value

编辑:我的意思是说,即使absconstexpr,你可以平凡编写自己的abs这是constexpr。 Coulda发誓我编辑它。

+1

在C++ 11中'abs'是否定义为'constexpr'? – Nawaz

+0

据我所见,'std :: abs'没有被定义为'constexpr'。 – interjay

+0

不,它不是,但是,呃,5票... –