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が出力されることに注意してください)。

テンプレートを削除することはオプションではないことに注意してください。この例は、配列を含む型をテンプレートにする必要があるコードで発生している問題を再現するために作成しました。

ありがとう

4

2 に答える 2

7

それは明確に定義されています。m_kAクラス定義では、は型で宣言されていることに注意してくださいfloat[]。これは不完全な型であり、と組み合わせて使用​​することはできませんsizeof。の定義ではm_kA、タイプが再宣言されfloat[3]、その後はを使用できますsizeof。(8.3.4は配列宣言の意味を支配します。)

3.4.6から-ディレクティブと名前空間エイリアス[basic.lookup.udir]:

10型のすべての調整後(typedef(7.1.3)がそれらの定義に置き換えられる間)、配列オブジェクトの宣言が配列型を指定できることを除いて、特定の変数または関数を参照するすべての宣言によって指定される型は同一でなければなりません。バインドされた主要な配列の有無によって異なります(8.3.4)。タイプIDに関するこのルールの違反は、診断を必要としません。

3.9.2複合タイプ[basic.compound]から:

6 [...]配列オブジェクトの宣言された型は、サイズが不明な配列である可能性があるため、変換ユニットのある時点で不完全であり、後で完了する可能性があります。これらの2つのポイントでの配列タイプ(「Tの未知の境界の配列」と「NTの配列」)は異なるタイプです。[...]

m_kAコンパイラの問題の回避策は、完全な型で完全に宣言することです。サイズを保持している別の静的メンバーも役立つ可能性があります。

[私はC++11から引用していますが、私の知る限り、C++03は同じ規則に従いました。]

于 2012-09-18T21:16:44.043 に答える
6

http://ideone.com/3ssVi

G++で正常にコンパイルされます。

私が見る限り、それはこのバグに関連している可能性があります:

http://connect.microsoft.com/VisualStudio/feedback/details/759407/can-not-get-size-of-static-array-defined-in-class-template

于 2012-09-18T21:11:18.583 に答える