2012-03-02 6 views
2

データを取得して処理する関数を記述する必要があります。このデータは、いくつかの方法(データ・セグメントに、ヒープ上、共有メモリ・セグメント上など)に割り当てられることがあります。dataを動的に割り当てることができるので、C++:unknow deleterを持つunique_ptr

T *data; 
if(global) data = &d; 
if(heap) data = new T [ size ]; 
if(shm) data = (T*) shmat(id, 0, 0); 
// processing data ... 

私は最善の方法だと思うだろうそれを処理するには、unique_ptrまたは他の種類のスマートポインタを使用しています。しかし、常に動的に割り当てられているわけではありません。実行時にdeleterをunique_ptrに選択する必要がありますが、それは不可能です。

dataを定義して処理する方法を教えてください。

enum DataPointerType 
{ 
    Stack, 
    Dynamic, 
    SharedMem, 
    ... 
}; 

template <class T> 
class DataPointer 
{ 
public: 
    DataPointer(T* pointer, DataPointerType type) 
     : _ptr(pointer), _type(type) 
    { } 

    ~DataPointer() 
    { 
     switch (type) { 
     case Stack: break; 
     case Dynamic: delete _ptr; _ptr = nullptr; break; 
     ... 
     } 
    } 

    T& operator*() { return *_ptr; } 
    const T& operator*() const { return *ptr; } 

    T* operator->() { return _ptr; } 
    const T* operator->() const { return ptr; } 

private: 
    T* _ptr; 
    DataPointerType _type; 

    // Prevent copying and destruction, dangerous 
    DataPointer(const DataPointer& other); 
    DataPointer& operator=(const DataPointer& other); 
}; 
+3

興味深い関連の読み取り:[より良いアロケータに向けてモデル](http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cts=1330701318745&ved=0CCYQFjAA&url=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22 %2Fwg21%2Fdocs%2Fpapers%2F2005%2Fn1850.pdf&gt; A-RQT-DXBeXA0QGJqqXFDQ&usg = AFQjCNFS07GH0af749GIyOIjE-QCc-K7dw&sig2 = hBWQcfg-EUOmH2d8UI5UuQ)。これは、型の一部であるDeleterの型が、単一の関数で異なるDeleter型を持つ 'unique_ptr'の使用を中断する特殊なケースです...私の推奨事項:deleterで型削除を実行する際に' shared_ptr'を使用してください。 .. –

答えて

6

カスタムデリターを実行時の値にすることができます。

KennyTmの良い答えに加えて
struct MyCustomDeleter 
{ 
    MemoryType type; 
    template <typename T> 
    void operator()(T* value) const 
    { 
     switch (type) 
     { 
     case MemoryType::heap: 
      delete[] value; 
      break; 
     case MemoryType::shm: 
      unmap_from_shm(value); 
      break; 
     // etc. 
     } 
    } 
}; 

... 

std::unique_ptr<T, MyCustomDeleter> ptr (new T[size], 
             MyCustomDeleter{MemoryType::heap}); 
+0

私はあなたの問題を解決するために提案したものと同様のソリューションを使用しました。とにかく私のコードは本当に醜いです...私は実際にこれを実装する方法については、今後数日で新しい質問をすることについて考えています。ありがとう! :) – peoro

1

は、選択した削除手段を使用して独自のスマートポインタを使用してください。そのカスタムディテクタはクラステンプレートパラメータに依存しません。

3

私はstd::unique_ptrについてはよく分からないが、あなたはstd::shared_ptrを使用することができます。

+2

これは動作しますが、deleter上で型消去を行う 'unique_ptr'のバージョンに必要なものを越える追加のオーバーヘッドがあります。参照カウントを維持する際の余分な増減はおそらく問題ではありませんが、スレッドセーフのインクリメントとデクリメントです。それでも、最初のパスでこれを使うのは、自分のスマートなポインターを書いておくよりも、まず重要です。 – bames53

+0

@ bames53:ケニーが提案したように、私はカスタムディレクターを選ぶでしょう。 –

1

shared_ptr<>を共有する場合は、実行時に削除プログラムを選択することができます。あなたがコピーしない限り/ shared_ptrは、unique_ptrと同じように動作するはずです。

+0

もちろん、 'unique_ptr'の値の一部は、あなたが誤ってコピーを作成するのを防ぎます。 – bames53

3

、別の可能性はあなたのデリータとして関数ポインタを使用することで、その後、実行時に異なる機能を提供する:

typedef std::unique_ptr<T, void(*)(void*)> Ptr; 
void delete_global(void*); 
void delete_heap(void*); 
// etc. 

Ptr get(/* whatever */) 
{ 
    if (...) 
     return Ptr(data, delete_global); 
    if (...) 
     return Ptr(data, delete_heap); 

    // etc. 
} 
関連する問題