#include <iostream>
#include <string>
#include <typeindex>
#include <memory>
class any {
public:
any(void) : index_(std::type_index(typeid(void))) {
}
any(const any &other) : ptr_(other.clone()), index_(other.index_) {
}
any(any &&other) : ptr_(std::move(other.ptr_)), index_(other.index_) {
}
template <typename U, class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, any>::value, U>::type>
any(U &&value) : ptr_(new derived<typename std::decay<U>::type>(std::forward<U>(value))), index_(std::type_index(typeid(typename std::decay<U>::type))) {
}
any& operator = (const any &other) {
if (ptr_ == other.ptr_) {
return *this;
}
ptr_ = other.clone();
index_ = other.index_;
return *this;
}
bool is_full() const {
return !bool(ptr_);
}
template<typename U>
bool is() const {
return std::type_index(typeid(U)) == index_;
}
template <typename U>
U& any_cast() {
if (is_full()) {
std::cout << "can not cast from " << typeid(U).name() << " to " << index_.name() << std::endl;
throw std::bad_cast();
}
auto d = dynamic_cast<derived<U>*>(ptr_.get());
return d->value;
}
private:
struct base;
using base_ptr = std::unique_ptr<base>;
base_ptr ptr_;
std::type_index index_;
struct base {
virtual base_ptr clone() const = 0;
};
template <typename T>
struct derived : base {
template <typename U>
derived(U &&val) : value(std::forward<U>(val)) {
}
base_ptr clone() const {
return base_ptr(new derived<T>(value));
}
T value;
};
base_ptr clone() const {
if (ptr_ != nullptr) {
return ptr_->clone();
}
return nullptr;
}
};
int main() {
any n;
std::cout << n.is_full() << std::endl;
std::string str("hello c++.");
n = str;
try {
std::cout << n.any_cast<std::string>() << std::endl;
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
any n1 = 1;
try {
std::cout << n1.any_cast<int>() << std::endl;
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
return 0;
}