2

組み込み MCU プロジェクト用に非常に単純なプール アロケータを作成しました。これは、次のインターフェイスを持つテンプレート化されたクラスです (実装部分はスキップされます。興味がある場合は投稿できます)。

template <typename T, size_t size>
class SimplePoolAllocator
{
public:
    SimplePoolAllocator();
    T * allocate();
    void deallocate(T *pointer);
...
}

クラスやPODなどの「単純な」ものには完全に機能します。次に例を示します。

SimplePoolAllocator<double, 10> poolOfDouble; // returns "double *"
SimplePoolAllocator<WeirdClass, 5> poolOfObjects; // returns "WeirdClass *"

固定サイズの配列に使用したい場合、問題が発生します。もちろん、この使用は生データ バッファ用です。私のプロジェクトでは、2 つの「転送」タイプがあり、1 つには 16 バイト、もう 1 つには 100 があります。

したがって、次のように sth を使用するとします。

SimplePoolAllocator<uint8_t[16], 10> pool1;
SimplePoolAllocator<uint8_t[100], 10> pool2;

すべて問題ないように見えますが、問題は、allocate() が "uint8_t(*)[16]" および "uint8_t(*)[100]" のような sth を返すことです。その場合、理想的には「uint8_t *」(先頭へのポインター) だけを返したいと思います。

私はそのようにできることを知っています:

uint8_t *p = *pool1.allocate(); // additional asterisk to "drop" the array thing from the type

しかし、これは...奇妙に見えます...

問題は、SimplePoolAllocator のインターフェイス (または何か) を改善して、「プレーンな」オブジェクト (上記のようなクラスと POD) と固定サイズの配列の両方の単純な割り当てをサポートし、最初の要素へのポインターだけを返すにはどうすればよいかということです。std::array を使用せずに、その data() メンバー関数を使用せずに、またはあちこちに「*」を追加せずに実行できますか? C++11 の機能は私には問題ありません。このような型を「変換」する sth があれば、ここで私を救うことができます: WeirdClass -> WeirdClass *, uint8_t[16] -> uint8_t *. 「生の」形式で割り込みで転送を処理するため、クラスでバッファーを簡単にラップすることはできません。必要なのはバッファーへのポインターだけで、後でメッセージキューを介してタスクに渡され、「タイプ」で処理されます。メッセージの要素の 1 つとして (サイズ)。可能であれば、この単純なタスクに仮想関数を使用することは避けたいです (;

それはまったく行うことができますか、それとも私が求めすぎているのでしょうか? おそらく唯一の解決策は、テンプレート sth へのインターフェイスを次のようにすることです。

template <typename T, size_t array_size, size_t size>

だから私は持っているだろう:

SimplePoolAllocator<WeirdClass, 1, 10> pool1;
SimplePoolAllocator<uint8_t, 16, 10> pool2;

しかし、これもあまりよく見えません...

提案がある場合は、事前に Thx をお寄せください。この質問はマイクロコントローラーのプロジェクトに関するものであるため、Boost や sth を使用することは問題外であることに注意してください。

4

1 に答える 1

5

クラスを特化する必要があります。

template <typename T, size_t size>
class SimplePoolAllocator
{
public:
    SimplePoolAllocator();
    T * allocate();
    void deallocate(T *pointer);
...
};

template <typename T, size_t N, size_t size>
class SimplePoolAllocator<T[N],size> // <-- here
{
public:
    SimplePoolAllocator();

    // you can now use different signatures and different implementations:
    T ** allocate();
    void deallocate(T **pointer);
...
};

これはおそらく、これらのケースを分離して個別に扱う最も簡単な方法です。

于 2013-10-20T08:51:48.993 に答える