2012-09-18 121 views
7

下面的代碼看起來好像沒什麼問題:C2070 - 非法的sizeof操作

#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完全相同的東西)。

注意,除去模板不是一個選項,我提出這個實例來再現,我在代碼林具有其中i需要包含數組的類型是一個模板的問題。

由於

+1

FWIW,在編譯GCC 4.7.1罰款:http://liveworkspace.org/code/19f48dbdb07463b08a310c168ab59a67。看它是另一個MSVC錯誤或其他東西。 – chris

+0

我不認爲這個表達式正在計算你認爲它正在計算的內容。 – Nobody

+4

@Nobody'sizeof array/sizeof array [0]'是計算數組長度的常用術語。你認爲它計算的是什麼,或者你認爲其他人認爲它計算的是什麼? – hvd

回答

4

它明確界定。請注意,在類定義,m_kA聲明瞭float[]類型,這是一個不完整的類型,不能同步進行sizeof使用。在m_kA的定義,它是重新聲明有型float[3],在這之後是正常使用sizeof。 (8.3.4支配數組聲明的含義。)

從3.4.6 using指令和命名空間的別名[basic.lookup.udir]:

10的類型的所有調整之後(在此期間的typedef (7.1.3)通過它們的定義被置換),通過參照一個給定的變量或函數的所有聲明中指定的類型應是相同的,不同之處在於用於陣列對象聲明可以指定由一個主要的存在或不存在不同的陣列類型數組綁定(8.3.4)。在類型標識上違反此規則不需要診斷。

從3.9.2化合物類型[basic.compound]:

6 [...]的陣列對象的聲明類型可能是未知大小的陣列,並且因此是不完整的,在一個指向翻譯單位,稍後完成;這兩個點的數組類型(「T的未知邊界數組」和「N T數組」)是不同的類型。 [...]

解決您的編譯器問題的方法是將完整類型聲明爲m_kA。另一個擁有這個尺寸的靜態成員也可能有幫助。

[我是從C++ 11引用但就我所知的C++ 03遵循相同的規則。 ]

+1

如果C++允許我這樣做,那麼我將非常高興將初始化程序內聯。問題是,據我所知,我只能爲本地或全局變量,因此我無法爲它做一個模板。 也正如我之前所說,我發現很難證明在這個VC9,因爲如果我只刪除模板一切正常。 – valerio

+1

想一些更多的構造如[this](http://pastebin.com/tumC3NBU)(注意:無效的C++)是爲什麼類型*應該*可能仍然是'float []'而不是'float [3]'帶模板。但正如我們在現在刪除的討論中看到的那樣,這個類型真的是'float [3]'。 – hvd