Reputation: 33
I'm struggling with the following situation.
#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;
}
As you can observe above, the templated class 'Foo' has the template parameter 'maxval'. 'Foo' also holds a member, again a templated class, that uses the template parameter 'maxval' together with the function 'log2' in its template arguments for instantiation. However, the depicted code will not work since e.g. function calls cannot be part of constant expressions. Do you see any possibility to evaluate e.g. log2(maxval) during compile time and to use the result for further template arguments inside 'Foo'?
Thanks for your help. (I'm using GCC 4.1.2)
Upvotes: 3
Views: 184
Reputation: 1134
Templates expect compile-time values. The log2
function would need to be constexpr
for this to work (which it isn't).
You'd have to define your own constexpr
function. In the case of a logarithm function to the base 2 it can work if you need an integer (cutting off the floating point part):
constexpr int log2(int number, int acc = 0) {
return number <= 1 ? acc : log2(number / 2, acc + 1);
}
Edit:
I did not notice that the question asked for GCC 4.1, which does not support constexpr
. While you should try to upgrade if that option is available to you, you can also go for a template-based solution, as proposed in @Florian's answer.
Edit 2:
In case you do not want to rely on Boost, here is a simple template-based implementation you could use:
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;
};
Then you'd use it as log2<13>::value
, which would result in 3
.
Yet another edit:
The constexpr
implementation above will return 0
for 0
and negative numbers, which is a mistake. The logarithm is not defined for zero or negative values (in the real domain), so the function can be adjusted to throw an error (since it's getting a bit unreadable, I added some line breaks for formatting):
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);
}
Upvotes: 8