1

私は C++ の初心者で、テンプレートのしくみを理解したいと思っています。MyListそのため、組み込みのプリミティブ型とポインターの両方を含む可能性のある汎用リストを実装しました。関数では、removeポインターの型と組み込みを区別して、ポインターの背後にあるオブジェクトを削除し、組み込みはそのままにしておくことができるようにしたいと考えています。

ポインターまたは非ポインターのテンプレート タイプを区別するために、次の関数を作成しました。

// distinguish between pointer and non-pointer type of template variable
template<typename T> bool is_pointer(T t) {
    return false;
}

template<typename T> bool is_pointer(T* t) {
    return true;
}

リスト関数removeでは、ポインターをテストし、必要に応じて削除するというアイデアがありました。ただし、delete ステートメントはコンパイルされません。

template<typename T> void MyList<T>::remove() {
    ...
    if (is_pointer(temp->getContent())) {
        // delete object pointer points to
        T t = temp->getContent();
        cout << t;    // prints out address
        // delete t;  // produces compiler error (see below)
}

さまざまなタイプのリスト クラスをテストするmain.cpp中で、とりわけ以下を呼び出します。

MyList<int> mylist;                // with type int
mylist.remove();
mylist.add(3);
// add and remove elements

MyList<string> mylist2;           // with type string
...

MyList<string*> mylist3;          // with type string*
mylist.add(new string("three")); 
mylist.remove();

ステートメントをコメント アウトdelete t;すると、制御フローが正しいことを確認できます。if ステートメントはstring*例としてのみ入力されています。ただし、deleteステートメントのコメントを外すと、コンパイラは次のように文句を言います。

../mylist.h: In member function ‘void MyList<T>::remove() [with T = int]’:
../main.cpp:36:18:   instantiated from here
../mylist.h:124:6: error: type ‘int’ argument given to ‘delete’, expected pointer
../mylist.h: In member function ‘void MyList<T>::remove() [with T = std::basic_string<char>]’:
../main.cpp:71:18:   instantiated from here
../mylist.h:124:6: error: type ‘struct std::basic_string<char>’ argument given to ‘delete’, expected pointer
make: *** [main.o] Error 1

見えないって何?ポインターに対してのみステートメントを使用してdeleteいますが、それでもこれらのコンパイラ エラーが発生します。iftステートメントで出力すると、それはポインター アドレスです。

4

3 に答える 3

1

テンプレートは、青写真の使用に基づいて型を実際に作成するためにコンパイラが使用する青写真です。テンプレートを使用するintstring*、コンパイラは実際に の 2 つのバリエーションを作成MyListし、T を実際の型に置き換えます。int を削除しても意味がないため、intforを使用する実装は偽物です。Tコンパイラが生成する実際のコードは次のとおりです。

int t = temp->getContent();
cout << t;
delete t;

あなたが理解できるように、これは間違っています。

于 2013-09-19T09:51:11.970 に答える
0

でテンプレートをインスタンス化するとT = int、次のようになります。

void MyList::remove() {
    if (false) {
        T t = temp->getContent();
        cout << t;
        delete t;
    }
}

コード ブロックが実行されない場合でも、構文的に正しい必要があります。

于 2013-09-19T09:58:17.747 に答える
0

このように C++ 11 の type_traits と auto_ptr を使用することをお勧めします

#include <type_traits>
template<typename T> void MyList<T>::remove() {
    ...
    if (is_pointer(T)) {
        // delete object pointer points to
        T t = temp->getContent();
        cout << t;    // prints out address
        auto_ptr tempobj(T);
}

また、コンパイラが C++ 11 に準拠していない場合に役立つ、型がテンプレート関数内のポインターであるかどうかを判断するも参照してください。

ありがとうニラジ・ラティ

于 2013-09-19T09:58:24.313 に答える