模板元编程:“没有整数或枚举类型”

时间:2017-07-02 13:28:20

标签: c++ templates floating-point template-meta-programming

我正在尝试使用模板编写“电源”功能。

#define VAR_X 2.0f

template <int N> struct Power
{
    static const float ret = VAR_X * Power<N-1>::ret;
};

template <> struct Power<0>
{
    static const float ret = 1.0f;
};

我为变量使用了一个宏,因为浮点数不能用作模板参数。当我尝试用g ++ 5.4.0编译时,我得到了这个:

tmptrig.cpp: In instantiation of ‘const float Power<1>::ret’:
tmptrig.cpp:35:28:   required from here
tmptrig.cpp:17:24: error: the value of ‘Power<0>::ret’ is not usable in a constant expression
     static const float ret = VAR_X * Power<N-1>::ret;
                        ^
tmptrig.cpp:22:24: note: ‘Power<0>::ret’ does not have integral or enumeration type
     static const float ret = 1.0f;

但是,当我将程序更改为仅处理整数时,它可以正常工作。

#define VAR_X 2

template <int N> struct Power
{
    static const int ret = VAR_X * Power<N-1>::ret;
};

template <> struct Power<0>
{
    static const int ret = 1;
};

我知道浮点数不能用作模板参数,但(据我所知)并不是这里的处理方式。当我使用浮动时,为什么编译器不喜欢它?

修改:这就是我main的样子:

int main(int argc, char *argv[])
{
    std::cout << Power<1>::ret << std::endl;
}

2 个答案:

答案 0 :(得分:1)

问题不在于浮点数不能是常量表达式,因为它们可以(尽管不允许作为模板非类型参数)。问题是你的代码需要明确标记它们,或者它们不能在类定义本身中初始化。

#include <iostream>

float constexpr var_x = 2.0f;

template <int N> struct Power
{
    static constexpr float ret = var_x * Power<N-1>::ret;
};

template <> struct Power<0>
{
    static constexpr float ret = 1.0f;
};

int main(int argc, char *argv[])
{
    std::cout << Power<1>::ret << std::endl;
}

它与原始意图几乎相同,因为constexpr暗示const

Clang提供了有关原始代码的更有用的警告:

error: in-class initializer for static data member of type 'const float' requires 'constexpr' specifier [-Wstatic-float-init]
    static const float ret = VAR_X * Power<N-1>::ret;

它们甚至可以在C ++ 03中成为常量表达式(以及元函数的结果),但这需要一个不合逻辑的定义:

float const var_x = 2.0f;

template <int N> struct Power
{
    static const float ret;
};

template <int N>
const float Power<N>::ret = var_x * Power<N-1>::ret;

template <> struct Power<0>
{
    static const float ret;
};

const float Power<0>::ret = 1.0f;

答案 1 :(得分:0)

publishedOn版本的工作原因是因为它作弊。

来自[class.static.data]

  

如果非易失性非内联const静态数据成员是整数或枚举类型,则其在类定义中的声明可以指定一个括号或等于初始化器,其中每个初始化器 - 赋值表达式是一个常量表达式

有关如何实际编写正确的代码,请查看StoryTeller's answer