我正在努力应对以下情况。
#include "systemc.h"
template<int maxval>
class Foo {
/* Error: calls to constructors and functions cannot be part of a constant expression */
sc_uint<int(log2(double(maxval)))> a;
...
};
int main() {
Foo<10> foo;
...
return 0;
}
如上所述,模板化类'Foo'具有模板参数'maxval'。 'Foo'还拥有一个成员,同样是一个模板化的类,它在模板参数中使用模板参数'maxval'和函数'log2'进行实例化。 但是,所描述的代码将不起作用,例如,函数调用不能是常量表达式的一部分。 你认为有可能评估,例如在编译期间使用log2(maxval)并将结果用于'Foo'中的其他模板参数?
感谢您的帮助。 (我正在使用GCC 4.1.2)
答案 0 :(得分:8)
模板需要编译时值。 log2
函数需要constexpr
才能实现(不是)。
您必须定义自己的constexpr
功能。对于基数2的对数函数,如果需要整数(切除浮点部分),它可以工作:
constexpr int log2(int number, int acc = 0) {
return number <= 1 ? acc : log2(number / 2, acc + 1);
}
修改强>
我没有注意到问题是GCC 4.1,它不支持constexpr
。如果您可以尝试升级该选项,您也可以使用@ Florian的答案中提出的基于模板的解决方案。
编辑2:
如果您不想依赖 Boost ,可以使用以下基于模板的简单实现:
template<int V>
struct log2 {
static int const value = 1 + log2<V/2>::value;
};
template<>
struct log2<0> {};
template<>
struct log2<1> {
static int const value = 0;
};
然后您将其用作log2<13>::value
,这将导致3
。
另一个编辑:
上面的constexpr
实施将为0
和负数返回0
,这是一个错误。对数值没有为零值或负值定义(在实际域中),因此可以调整函数以引发错误(因为它有点不可读,我为格式化添加了一些换行符):
constexpr int log2(int number, int acc = 0) {
return number <= 0
? throw std::logic_error{"Logarithm of zero or negative number not allowed."}
: number == 1
? acc
: log2(number / 2, acc + 1);
}