函数调用模板参数

时间:2016-05-02 07:26:03

标签: c++ gcc

我正在努力应对以下情况。

#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)

1 个答案:

答案 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);
}