- #include <type_traits> 
- #include <memory> 
- #include <iostream> 
-   
- namespace detail 
- { 
-     template <typename T> 
-     struct wrapper 
-     { 
-         virtual ~wrapper() {} 
-         virtual T const * get() const = 0; 
-         virtual T * get() = 0; 
-     }; 
-   
-     template <typename T, typename F> 
-     struct storage 
-         : wrapper<T> 
-     { 
-         storage(F f) 
-         { 
-             p_ = f(); 
-         } 
-   
-         T const * get() const { return p_.get(); } 
-         T * get() { return p_.get(); } 
-   
-         private: 
-             typename std::result_of<F()>::type p_; 
-     }; 
- } 
-   
- template <typename T> 
- class some_class 
- { 
-     public: 
-         template <typename F> 
-         void store(F f) 
-         { 
-             storage_.reset(new detail::storage<T, F>(f)); 
-         } 
-   
-         T const * get() const { return storage_->get(); } 
-         T * get() { return storage_->get(); } 
-   
-     private: 
-         std::unique_ptr<detail::wrapper<T>> storage_; 
- }; 
-   
- struct foo 
- { 
-     void bar() const { std::cout << "hello" << '\n'; } 
- }; 
-   
- int main() 
- { 
-     some_class<foo> a; 
-     a.store([]() { return std::unique_ptr<foo>(new foo()); }); 
-     a.get()->bar(); 
-     a.store([]() { return std::unique_ptr< 
-         foo, std::default_delete<foo[]> 
-     >(new foo[1], std::default_delete<foo[]>()); }); 
-     a.get()[0].bar(); 
-   
-     return 0; 
- } 
				I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8bWVtb3J5PgojaW5jbHVkZSA8aW9zdHJlYW0+CgpuYW1lc3BhY2UgZGV0YWlsCnsKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogICAgc3RydWN0IHdyYXBwZXIKICAgIHsKICAgICAgICB2aXJ0dWFsIH53cmFwcGVyKCkge30KICAgICAgICB2aXJ0dWFsIFQgY29uc3QgKiBnZXQoKSBjb25zdCA9IDA7CiAgICAgICAgdmlydHVhbCBUICogZ2V0KCkgPSAwOwogICAgfTsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgRj4KICAgIHN0cnVjdCBzdG9yYWdlCiAgICAgICAgOiB3cmFwcGVyPFQ+CiAgICB7CiAgICAgICAgc3RvcmFnZShGIGYpCiAgICAgICAgewogICAgICAgICAgICBwXyA9IGYoKTsKICAgICAgICB9CgogICAgICAgIFQgY29uc3QgKiBnZXQoKSBjb25zdCB7IHJldHVybiBwXy5nZXQoKTsgfQogICAgICAgIFQgKiBnZXQoKSB7IHJldHVybiBwXy5nZXQoKTsgfQoKICAgICAgICBwcml2YXRlOgogICAgICAgICAgICB0eXBlbmFtZSBzdGQ6OnJlc3VsdF9vZjxGKCk+Ojp0eXBlIHBfOwogICAgfTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmNsYXNzIHNvbWVfY2xhc3MKewogICAgcHVibGljOgogICAgICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBGPgogICAgICAgIHZvaWQgc3RvcmUoRiBmKQogICAgICAgIHsKICAgICAgICAgICAgc3RvcmFnZV8ucmVzZXQobmV3IGRldGFpbDo6c3RvcmFnZTxULCBGPihmKSk7CiAgICAgICAgfQoKICAgICAgICBUIGNvbnN0ICogZ2V0KCkgY29uc3QgeyByZXR1cm4gc3RvcmFnZV8tPmdldCgpOyB9CiAgICAgICAgVCAqIGdldCgpIHsgcmV0dXJuIHN0b3JhZ2VfLT5nZXQoKTsgfQoKICAgIHByaXZhdGU6CiAgICAgICAgc3RkOjp1bmlxdWVfcHRyPGRldGFpbDo6d3JhcHBlcjxUPj4gc3RvcmFnZV87Cn07CgpzdHJ1Y3QgZm9vCnsKICAgIHZvaWQgYmFyKCkgY29uc3QgeyBzdGQ6OmNvdXQgPDwgImhlbGxvIiA8PCAnXG4nOyB9Cn07CgppbnQgbWFpbigpCnsKICAgIHNvbWVfY2xhc3M8Zm9vPiBhOwogICAgYS5zdG9yZShbXSgpIHsgcmV0dXJuIHN0ZDo6dW5pcXVlX3B0cjxmb28+KG5ldyBmb28oKSk7IH0pOwogICAgYS5nZXQoKS0+YmFyKCk7CiAgICBhLnN0b3JlKFtdKCkgeyByZXR1cm4gc3RkOjp1bmlxdWVfcHRyPAogICAgICAgIGZvbywgc3RkOjpkZWZhdWx0X2RlbGV0ZTxmb29bXT4KICAgID4obmV3IGZvb1sxXSwgc3RkOjpkZWZhdWx0X2RlbGV0ZTxmb29bXT4oKSk7IH0pOwogICAgYS5nZXQoKVswXS5iYXIoKTsKCiAgICByZXR1cm4gMDsKfQ==