C2070 - 非法的sizeof操作数

9
以下代码在我看来很好:
    #include <stdio.h>

    template <typename T>
    struct A
    {
        static float m_kA[];
    };

    template <typename T>
    float A<T>::m_kA[] = {1.0f, 2.0f, 3.0f};

    int main()
    {
        printf("%d\n", 
            sizeof(A<unsigned int>::m_kA) /
            sizeof(A<unsigned int>::m_kA[0]));
        return 0;
    }

但是当我使用VC9编译时,出现了以下错误。
error C2070: 'float []': illegal sizeof operand

我希望这段代码可以编译。我是否遗漏了什么?有人知道如何解决这种奇怪的行为吗(请注意,没有模板的完全相同的内容可以编译并输出3)。
请注意,删除模板不是一个选项,我制作了这个例子来重现我在需要数组类型包含模板的代码中遇到的问题。
谢谢

2
顺便说一下,在GCC 4.7.1上编译正常:http://liveworkspace.org/code/19f48dbdb07463b08a310c168ab59a67。可能会是又一个MSVC的bug或其他什么问题。 - chris
我认为这个表达式计算的不是你想要计算的内容。 - Nobody moving away from SE
4
sizeof array / sizeof array[0] 是一种常见的用语,用于计算数组的长度。你认为它计算的是什么,或者你认为其他人认为它计算的是什么? - user743382
1
关于实际问题,是否有选项(即使有些麻烦)在类内声明中明确指定数组的长度? - user743382
@Nobody 是的,没错。只要你在处理数组,它就永远不会计算出错误的结果:如果长度已知,它将给出正确的结果;如果长度未知,则会给出一个编译器错误。 - user743382
显示剩余5条评论
2个回答

7
这是一个明确定义的问题。请注意,在类定义中,m_kA 声明为 float[] 类型,这是一种不完整类型,不能与 sizeof 配合使用。在 m_kA 的定义中,它被重新声明为 float[3] 类型,此后可以使用 sizeof。(8.3.4 规定了数组声明的含义。)
来自于 3.4.6 "Using-directives and namespace aliases" [basic.lookup.udir]:
10 在所有类型调整之后(其中 typedef(7.1.3)被替换为其定义),引用给定变量或函数的所有声明指定的类型必须相同,除了数组对象的声明可以指定不同的数组类型,区别在于是否具有主要数组维度(8.3.4)。对类型标识符违反此规则并不需要进行诊断。
来自于 3.9.2 "Compound types" [basic.compound]:
6 [...] 数组对象的声明类型可能是未知大小的数组,因此在翻译单元的某个时刻是不完整的,而后来变成完整的;这两个时间点的数组类型(“T 类型的未知大小数组”和 “N T 类型的数组”)是不同的类型。[...]
解决编译器问题的一个方法是直接用完整类型声明 m_kA。另外一个静态成员变量来存储数组大小也可能会有帮助。
[我引用的是 C++11 的文档,但据我所知,C++03 遵循相同的规则。]

1
如果C++允许我这样做,我会非常高兴地将初始化程序内联。问题在于据我所知,我只能对局部或全局变量这样做,因此我无法为其创建模板。 另外,正如我之前所说,我觉得很难在这方面证明VC9的必要性,因为如果我只删除模板,一切都可以正常工作。 - valerio
1
再仔细思考一下,像this这样的结构(注意:不是有效的 C++)可能是类型应该保持为 float[] 而不是 float[3] 的合理原因。但正如我们在已删除的讨论中所看到的,类型确实是 float[3] - user743382

6

报告的错误显示了我遇到的相同问题,我只是尝试找到一个解决方法。 - valerio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接