VC++6.0 と ISO C++ の違い

up
 C2555などのコードはVCのエラーコードです。ISO C++の文法通りだがVCのバグで VCではコンパイルエラーになるということです。以下は全てVCがISO C++に対応できてない項目です。
  1. C2555:戻り値型がCovariantの仮想関数
  2. C2667:テンプレート関数のPartial Ordering
  3. C2065:完全なKoenig Lookupは演算子に関してのみ
  4. 明示的に特定したテンプレート関数は正確にオーバーロード出来ない
  5. C2989,C2988:クラステンプレートの部分特別バージョンがサポートされていない
  6. C2059:メンバテンプレートをクラス定義の外部で定義できない
  7. C2954:テンプレート引数にクラステンプレートを使用できない


  1. C2555:戻り値型がCovariantの仮想関数
    [症状]
    コンパイラが、標準C++(10.3)で明示されているcovariantの戻り値の型を持つ 仮想関数をサボートしていない。

    [原因]
    オーバーライドした関数の5つの戻り値型は、オーバーライドされた全く同じ である、関数の戻り値型か、関数のクラスのcovariantのいずれかです。

    class B {
    public :
        virtual B* f( ):
    }
    class D : public B {
    public :
        D* f( );
    }
    
     関数D::f が 関数B::f をオーバーライドしているとすると、 次の基準を満たせば関数の戻り値型は covariant です。

    (*)cv修飾子(cv-qualification)const、volatile、const volatile の修飾子


  2. C2667:テンフレート関数のPartial Ordering
    [症状]
     テンプレート関数のPartial Orderingを使用しようとすると、C2667のエラーとなる。

    [原因]
    コンパイラが、標準C++(14.5.5.2) で明示されているテンプレート関数のPartial Orderingをサポートしていない。 ARMの第19章§14.4 にもPartial Orderingと言う言葉はないものの同説明がなされています。 引用します。

     ある呼び出しに対して複数のテンプレート関数を選択することができる場合、 最も具体的に引数が指定されているテンプレート関数が選択される。例をあげる。
    template<class T> void f(T);             // #1
    template<class T> void f(T*);            // #2
    template<class T> void f(vector<T>*);    // #3
    
    void g(int i, char* pc, vector<int>* pv)
    {
        f(i);       // #1 が使われる
        f(pc);      // #2 が使われる
        f(pv);      // #3 が使われる
    }
    
    試しにテストソース(1KB)を作成してみました。 やはりVC6.0(SP3)ではコンパイルエラーになります。が、g++では正常にコンパイルできます。


  3. C2065:完全なKoenig Lookupは演算子に関してのみ
    [症状]
     Koenig Lookupとして知られるArgument-dependent name loockup は演算子にしか 働かない。それは名前空間内で非正規化関数となる。

    [原因]
    コンパイラが標準C++で記されているArgument-dependent name lookup を完全に サポートしていない。標準C++(3.4.2) を参照すべし。そこにはArgument-dependenet name lookup に関する情報が記されている。

    // compiler option : -GX
    #include <iostream>
    namespace T {
        struct T2 {
        };
        void g( T2 ) {
        }
        T2 operator+( T2 a, T2 b ) {
            std::cout << "in T2::+" << std::endl;
            return b;
        }
    }
    
    int main( ) {
        T::T2 t1, t2;
        
        g( t1 );       // error C2065 (引数型から関数を特定できない)
        t1 + t2;       // operator OK
        return 0;
    }
    
    (*) Koenig とは C++功労者Andrew Koenigのことであろう:-)


  4. 明示的に特定したテンプレート関数は正確にオーバーロード出来ない
    [症状]
     全てのテンプレート引数が関数の引数で使われなかったり、テンプレート関数の 戻り値が使われなかったりしたら、テンプレート関数は正確にオーバーロードできない。

    [原因]
     コンパイラがテンプレート関数名を正確に装飾する上でこのバグが存在する。 Name Decoration は引数と戻り値型を使用し、明示的に特定されたテンプレート引数型 を使わない。 それゆえ、これら全てのテンプレート関数のインスタンス化は同じ修飾された名前と なる。

     明示的な(explicit)テンプレート引数の使用は標準C++ ( 14.8.1)にあります。

    [備考]
     このバグはコンパイルエラーもリンクエラーも起こさず、誤った実行結果を 出力します。ご注意下さい。

    //test.cpp
    // compiler option needed: /GX
    #include <iostream>
    
    // テンプレート引数(class T)が関数foo の引数となっていない
    // 戻り値も使われていない
    template <class T>
    void foo( void ) {
        std::cout << typeid( T ).name() << std::endl;
    }
    
    int main( ) {
        foo<bool>();
        foo<char>();
        foo<int>();
        return 0;
    }
    
    出力結果:
    int
    int
    int
    	


  5. C2989,C2988:クラステンプレートの部分特別バージョンがサポートされていない
    [症状]
     クラステンプレートの部分特別バージョンを使うとエラー(C2989)になる。

    [原因]
     コンパイラが標準C++( 14.5.4.1)で記されているクラステンプレートの部分特別バージョン をサポートしていない。

    //  プライマリテンプレート
    template<class T, int I> struct A {
        void f();
    };
    
    template<class T, int I> void A<T,I>::f() { }
    
    //  クラステンプレートの部分特別バージョン
    template<class T> struct A<T,2> {
        void f();
        void g();
        void h();
    };
    	


  6. C2059:メンバテンプレートをクラス定義の外部で定義できない
    [症状]
     クラスの外でメンバテンプレート関数やメンバテンプレートクラスを定義したらエラーになる。

    [原因]
     コンパイラがメンバテンプレート関数やメンバテンプレートクラスのクラス外定義を サートしていない。 標準C++( 14.5.2)にメンバテンプレートに関する情報が記されている。

    template<class T> class string {
    public:
        template<class T2> int compare(const T2&);
        template<class T2> string(const string<T2>& s) {}  // インラインの定義はOK
        //  ...
    };
     
    // この定義がエラーとなる
    template <class T> template<class T2> int string<T>::compare(const T2& s)
    {
        //  body
    }
    	


  7. C2954:テンプレート引数にクラステンプレートを使用できない
    [症状]
     テンプレート引数にクラステンプレートを使用するとエラーになる。

    [原因]
     コンパイラがテンプレート引数としてテンプレートをサポートしていない。 標準C++( 14.1の第2段落)にテンプレート引数に関する情報が記されている。

    template<class T> class myarray { /* body */ };
    template<class U, class V, template<class T> class C = myarray>
    class Map {
        C<U> key;
        C<V> value;
    }
    	



by masu
e-mail: massun.masumoto@nifty.ne.jp
URL : http://member.nifty.ne.jp/~masumoto/