動的に型サイズを求めるスマポ

http://d.hatena.ne.jp/okzk/20060622#1150958620

から。動的にサイズを調べるのは以下のようなコードはどうでしょうか。先に言っておくと冗談です。 GCC と cl.exe で確認。たぶんきっと他でもだいたい動きますおそらく。

template<class T> class smart_ptr {
    T* p_;
    int size_;

    static int size_of(void* vp) {
        char* p = (char*)vp;
        void* vt = *(void**)p;
        for (p++; vt != *(void**)p; p++);
        return p-(char*)vp;
    }
public:
    explicit smart_ptr(T* p) : p_(p) {
#if 0 // 落ちる
        size_ = sizeof(T);
#else // 問題なし
        size_ = size_of(p);
#endif
    }
    T& operator[](int i) {
        return *(T*)((char*)p_+size_);
    }
};

#include <iostream>
using namespace std;

class Base {
public:
    virtual int get_val() {return 0;}
    virtual ~Base(){}
};

class Derived : public Base {
    int dmy;
public:
    virtual int get_val() {return 1;}
    virtual ~Derived(){}
};

void print_val(Base* base, int size) {
    smart_ptr<Base> p(base);
    for (int i = 0; i < size; ++i)
        cout << p[i].get_val() << endl;
}

int main() {
    Base base[2];
    print_val(base, 2);
    Derived derived[4];
    print_val(derived, 4);
    return 0;
}

仮定している内容は以下のこと。

  • 仮想関数の無いクラスはたぶん使えない。
  • smart_ptr のコンストラクタに渡したポインタは全て同じ型。
  • 仮想関数テーブルがクラスの先頭にある。
  • 配列サイズは2以上。

一個目の制限は、仮想関数のあるクラスか無いクラスか、は判定できる気がする…ので、解除できる気がしますが、ただのネタですし、なんかしんどいので省略。あと、テストとかいい加減なので間違ってるかも。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h