動的多相性を後付けできるか考えてみる.
結論:「出来るけど('A`)ノ マンドクセー」
#include <iostream> class triangle { public: void draw() const { std::cout << "triangle::draw" << std::endl; } }; class rectangle { public: void draw() const { std::cout << "rectangle::draw" << std::endl; } }; // ----- 以上,静的多相性のある2クラス ----- // ----- 以下,動的多相性を後付け ----- // triangleとrectangleの抽象基底クラスとして振舞うようなクラス class any_shape { class shape_holder_base { public: virtual void draw() const = 0; }; template<class T> class shape_holder : public shape_holder_base { public: shape_holder(T val = T()) : _val(val) { } virtual void draw() const { _val.draw(); } private: T _val; }; public: template<typename T> any_shape(T const &val) : _p(0) { _p = new shape_holder<T>(val); } ~any_shape() // throw() { delete _p; } template<typename T> any_shape &operator=(T const &val) { any_shape tmp(val); this->swap(tmp); return *this; } void draw() const { _p->draw(); } private: void swap(any_shape &r) { std::swap(_p, r._p); } shape_holder_base *_p; }; // 実験 int main() { any_shape sh = triangle(); sh.draw(); sh = rectangle(); sh.draw(); return 0; }
こういう要求があるなら最初から抽象クラスから派生しろ,ちゅーもんですな.普通に考えたら設計の失敗を実装でad hocに取り繕ってる,以上の評価はなさげ・・・.
あえて後付けしたほうが有利な点としては
- 多相的に扱わない場合,vptr(オブジェクト毎)による空間的オーバーヘッドがない
- クラス定義に触れずに動的多相性を追加できる
- メンバ関数の特殊化を使えば,signatureの異なるメソッドを多相的に扱うこともできることはできる
- グローバル関数にも動的多相性を持たせることは可能といえば可能
な感じ?1, 2の利点は案外大きいかも.any iteratorとかやろうとするならむしろこの後付けの方が最適解なのか.3, 4はこれが出来てうれしい状況ってあるんかいな.
結局,上の利点のどれかが決定的でない限り普通に抽象基底クラス作っとけよっていう.
実際にやるなら抽象基底クラスのスマポとして振舞うようなクラス作る方が空間的に効率的?
この動的多相性の後付けをgenericな形に出来るか考えてみたけれど,あんま簡単な形にはなりそうにないにゃー.