template で 後置 cast
OK。cast を後置したいのはよくわかった。しかし、C++ の Unum で union を使う必要があるのか? 使うとしても ananymous union でもいいような。あと、malloc がまずいと思うなら std::allocator を使うというソリューション。
まあ、そんなことより、どうせ C++ なら template を使えばいいんでないかい、ということで、template を使った別解。
#include <iostream> template<typename T> class Object { public: Object(const T& object) : obj(object) { } template<typename U> U cast() { return static_cast<U>(obj); } operator T&() { return obj; } Object<T>& operator=(const T& value) { obj = value; return *this; } private: T obj; }; int main() { Object<double> obj = 3.14; std::cout << obj << std::endl << obj.cast<int>() << std::endl; obj = 1.732; std::cout << obj << std::endl << obj.cast<int>() << std::endl; return 0; }
ポインタの方はこう。
#include <iostream> #include <string> #include <cstring> template<typename T> class ObjectPointer { public: typedef T* pointer; typedef T value_type; typedef T& reference; public: ObjectPointer(pointer p) : ptr(p) { } reference operator*() { return *ptr; } operator pointer() { return ptr; } ObjectPointer& operator=(pointer p) { ptr = p; return *this; } template<typename U> U ptr_cast() { return reinterpret_cast<U>(ptr); } template<typename U> U obj_cast() { return dynamic_cast<U>(ptr); } private: pointer ptr; }; class A { public: virtual ~A() { } virtual std::string to_s() { return std::string("A"); } }; class B : public A { public: virtual ~B() { } virtual std::string to_s() { return std::string("B"); } }; int main(int argc, char **argv) { const int bufsize = 1024; ObjectPointer<unsigned char> buffer = new unsigned char[bufsize]; ObjectPointer<A> a = new B; for (int i = 0; i < argc; i++) { std::strncpy(buffer.ptr_cast<char *>(), argv[i], bufsize); std::cout << buffer.ptr_cast<char *>() << std::endl; } std::cout << a.obj_cast<B*>()->to_s() << std::endl; delete a; delete[] buffer; return 0; }
いい加減に作ったので、あまりよろしくないところがあるかも。あと、まじめに考えると smart pointer として実装するとかいろいろあるけど、面倒というかまじめに作ってもあまり意味がないような気がするので、このへんで。