GCC拡張を使ったスマートポインタ

前回はcleanup属性を使ってデストラクタのような機能を実現する方法を取り上げました。今回はその応用として簡易的なスマートポインタを作ってみました。auto_ptrという名前を付けましたが、scoped_ptrのほうが適切だったかもしれません。

#include <stdio.h>
#include <stdlib.h>
 
#define auto_ptr(type) \
    __attribute__((cleanup(call_auto_ptr_dtor))) \
    struct { type * const ptr; void (* const dtor)(type*); }
 
void call_auto_ptr_dtor(void *ptr)
{
    typedef struct { void *ptr; void (*dtor)(void*); } temp_auto_ptr_t_;
    temp_auto_ptr_t_ *p = (temp_auto_ptr_t_*)ptr;
    void (*dtor_)(void*) = p->dtor;
    if (dtor_ != 0)
        dtor_ = &free;
    (*dtor_)(p->ptr);
}
 
void FILE_dtor(FILE *stream)
{
    if (stream != NULL)
        fclose(stream);
}
 
int main(void)
{
    auto_ptr(FILE) file = { fopen("foo.txt", "w"), &FILE_dtor };
    fputs("hello\n", file.ptr);
    return 0;
}

cleanup属性の使いにくいところは、関数からの返却値に対しては指定できない(正確には、指定はできるけれども無視される)ことです。この問題を回避するためにいろいろ工夫する必要があるのですが、どうしても利便性が損なわれてしまいます。

それ以外に、auto_ptrを他のオブジェクトに代入できないように、さらには後から内容を変更できないように工夫しています。

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/876