This code is based on boost :: any . It uses type erasure to store an arbitrary value and forbids it from being assigned. I stopped casting to lighten my eyes.
You may have some success in boost::any wrapper instead of bringing a complete reevaluation, but I'm not so sure and you will need to take care of the ghosts a bit.
It also prohibits copying and moving, because I cannot be bothered by the deal with this, but your full implementation should have it.
You also want to give him a name that makes more sense.
#include <typeinfo> #include <iostream> class reassign_any { public: reassign_any() : content_(nullptr) {} template <typename T> reassign_any(const T& x) : content_(new holder<T>(x)) {} ~reassign_any() { // no need to check for null delete content_; } reassign_any(const reassign_any&) = delete; reassign_any& operator=(const reassign_any&) = delete; reassign_any(reassign_any&&) = delete; reassign_any& operator=(reassign_any&&) = delete; bool empty() const { return !content_; } template <typename T> bool set(const T& t) { if(content_) { // check for type equality of held value and value about to be // set if(content_->type() == typeid(T)) { delete content_; content_ = new holder<T>(t); return true; } else { return false; } } else { // just create content_ = new holder<T>(t); return true; } } template <typename T> T* get() { return content_->type() == typeid(T) ? &static_cast<holder<T>*>(content_)->held : 0; } private: class placeholder { public: // structors virtual ~placeholder() { } virtual const std::type_info & type() const = 0; }; template<typename ValueType> class holder : public placeholder { public: // structors holder(const ValueType & value) : held(value) { } virtual const std::type_info & type() const { return typeid(ValueType); } public: // representation ValueType held; private: // intentionally left unimplemented holder & operator=(const holder &); }; private: placeholder* content_; }; int main() { reassign_any x; x.set(3); if(x.get<int>()) std::cout << "int set" << std::endl; if(x.set(3.f)) { std::cout << "this shouldn't be printed" << std::endl; } else { std::cout << "this should be printed" << std::endl; } if(x.set(23)) { std::cout << "this should be printed" << std::endl; } else { std::cout << "this shouldn't be printed" << std::endl; } return 0; }
Unrelated Note: Boost.TypeErasure recently went through a review. I would really like to try and implement this version of any of them, at least in order to see if the implementation allows.
source share