C++テンプレート静的メンバー定義(インスタンス化)

10924 ワード

質問:
次のようなテンプレートがあります.
template <typename T> class Test{

public:

    static std::string info;

};

 
次の定義方法のうち、正しいもの(コンパイルによるもの)はどれですか?
template <> string Test<int>::info("123");

template <typename T> string Test<T>::info("123");

template <typename T> string Test<T>::info;

template <> string Test<int>::info; 

template <> string Test<int>::info();

template <typename T> string Test<T>::info();

 
皆さんの分析判断に影響を与えないように、私は答えの色を比較的浅い色に変えました.次は答えです.
  • template <> string Test::info("123");//ok
  • template string Test::info("123");//ok
  • template string Test::info;//ok
  • template <> string Test::info;//error
  • template <> string Test::info();//error
  • template string Test::info();//error

  •  
    質問:
    まず、3つの正しい答えを説明します.
    第1の形式は特化定義と呼ばれ、テンプレートのある特化に静的メンバーの定義を提供する役割を果たし、私たちの例ではTestクラスの静的メンバーinfoにのみ定義を提供します.単一パラメータ構築関数の初期化を呼び出します.
    2つ目の形式は、通常のクラスの静的メンバーの定義と同様であり、このコンパイルユニットがテンプレートのすべての特化のためにその静的メンバーの定義を暗黙的に提供する役割を果たす.我々の例では、Test,Test,Test...静的メンバーの定義は暗黙的に提供され、単一パラメータコンストラクション関数の初期化が呼び出されます.
    3つ目の形式は2つ目の形式と一致し、唯一の違いはデフォルトの構造関数を使用して初期化することです.
    次に、3つの間違った答えを説明します.
    1つ目の形式は、デフォルトのコンストラクション関数を使用して初期化されたと考えている人が多いです.しかし、コンパイラは特化定義を特殊に処理し、定義ではなく宣言としてコンパイルします.なぜかというと、基準を制定した人に聞くべきだ.このような文法を実現するのは難しいかもしれないし、この文法もあいまいだと思います.
    2つ目の形式は、関数を宣言することではありません.
    3つ目の形式は、2つ目と同じです.
    詳細:
    2つの正しい定義方法には他にどのような違いがありますか?
    //a.cpp
    
    template <typename T> string Test<T>::info("4321");
    
        Test<int>::info
    
    //b.cpp
    
    template <typename T> string Test<T>::info("1234");
    
         Test<int>::info

     
    この2つの定義は異なるコンパイルユニットで共存することができ、Test::infoの初期値はいくらであり、これは静的メンバーとの初期化順序に依存するので、これは良いことではない.
    //a.cpp
    
    template <> string Test<int>::info("123");
    
    //b.cpp
    
    template <> string Test<int>::info("123");

     
    特化定義では、上記の方法ではコンパイルできません.
    //a.cpp
    
    template <> string Test<int>::info("123");
    
    
    
    //b.cpp
    
    template <typename T> string Test<T>::info("123");
    
    
    
        Test<int>::info      

    上記の方法ではコンパイルできません.
     
    一般的にコンパイルできないことを避けるためには、以下のような定義で使用を最小限に抑える必要があります.
    template <typename T> string Test<T>::info;

    最初に使用する必要があるときに実装ファイルに以下の特化定義を与えるだけで、他のファイルはヘッダファイルを含めるだけで使用できます.
    template <> string Test<int>::info("123");

    適用例:
    /*
    
     * Copyright (C) 2007 The Android Open Source Project
    
     *
    
     * Licensed under the Apache License, Version 2.0 (the "License");
    
     * you may not use this file except in compliance with the License.
    
     * You may obtain a copy of the License at
    
     *
    
     *      http://www.apache.org/licenses/LICENSE-2.0
    
     *
    
     * Unless required by applicable law or agreed to in writing, software
    
     * distributed under the License is distributed on an "AS IS" BASIS,
    
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    
     * See the License for the specific language governing permissions and
    
     * limitations under the License.
    
     */
    
    
    
    #ifndef ANDROID_UTILS_SINGLETON_H
    
    #define ANDROID_UTILS_SINGLETON_H
    
    
    
    #include <stdint.h>
    
    #include <sys/types.h>
    
    #include <utils/threads.h>
    
    #include <cutils/compiler.h>
    
    
    
    namespace android {
    
    // ---------------------------------------------------------------------------
    
    
    
    template <typename TYPE>
    
    class ANDROID_API Singleton
    
    {
    
    public:
    
        static TYPE& getInstance() {
    
            Mutex::Autolock _l(sLock);
    
            TYPE* instance = sInstance;
    
            if (instance == 0) {
    
                instance = new TYPE();
    
                sInstance = instance;
    
            }
    
            return *instance;
    
        }
    
    
    
        static bool hasInstance() {
    
            Mutex::Autolock _l(sLock);
    
            return sInstance != 0;
    
        }
    
        
    
    protected:
    
        ~Singleton() { };
    
        Singleton() { };
    
    
    
    private:
    
        //                ,               declare private,not define
    
        Singleton(const Singleton&);
    
        Singleton& operator = (const Singleton&);
    
        static Mutex sLock;
    
        static TYPE* sInstance;
    
    };
    
    
    
    /*
    
     * use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
    
     * (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
    
     * and avoid to have a copy of them in each compilation units Singleton<TYPE>
    
     * is used.
    
     * 
    
     * NOTE: we use a version of Mutex ctor that takes a parameter, because
    
     * for some unknown reason using the default ctor doesn't emit the variable!                 ,       !
    
     */
    
    //    Singleton,                  ,        static  ,         
    
    #define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE)                 \
    
        template<> Mutex Singleton< TYPE >::sLock(Mutex::PRIVATE);  \     
    
        template<> TYPE* Singleton< TYPE >::sInstance(0);           \     
    
        template class Singleton< TYPE >; \     
    
    
    
    
    
    // ---------------------------------------------------------------------------
    
    }; // namespace android