blob: dd6eaa5fb5d89ce7716268b2303c35f3a96f3653 [file] [log] [blame]
// Copy from evpp project
// @see https://github.com/Qihoo360/evpp/blob/master/evpp/any.h commit version c5038a6
#ifndef TUBEMQ_CLIENT_CPP_SRC_ANY_H_
#define TUBEMQ_CLIENT_CPP_SRC_ANY_H_
#include <assert.h>
#include <algorithm>
#include <typeinfo>
namespace tubemq {
// A variant type that can hold any other type.
//
// Usage 1 :
//
// Buffer* buf(new Buffer());
// Any any(buf);
// Buffer* b = any_cast<Buffer*>(any);
// assert(buf == b);
// delete buf;
//
//
// Usage 2 :
//
// std::shared_ptr<Buffer> buf(new Buffer());
// Any any(buf);
// std::shared_ptr<Buffer> b = any_cast<std::shared_ptr<Buffer>>(any);
// assert(buf.get() == b.get());
//
//
// Usage 3 :
//
// std::shared_ptr<Buffer> buf(new Buffer());
// Any any(buf);
// std::shared_ptr<Buffer> b = any.Get<std::shared_ptr<Buffer>>();
// assert(buf.get() == b.get());
//
class Any {
public:
Any() : content_(nullptr) {}
~Any() { delete content_; }
template <typename ValueType>
explicit Any(const ValueType& value) : content_(new Holder<ValueType>(value)) {}
explicit Any(const Any& other) : content_(other.content_ ? other.content_->clone() : nullptr) {}
public:
Any& swap(Any& rhs) {
std::swap(content_, rhs.content_);
return *this;
}
template <typename ValueType>
Any& operator=(const ValueType& rhs) {
Any(rhs).swap(*this);
return *this;
}
Any& operator=(const Any& rhs) {
Any(rhs).swap(*this);
return *this;
}
bool IsEmpty() const { return !content_; }
const std::type_info& GetType() const { return content_ ? content_->GetType() : typeid(void); }
template <typename ValueType>
ValueType operator()() const {
return Get<ValueType>();
}
template <typename ValueType>
ValueType Get() const {
if (GetType() == typeid(ValueType)) {
return static_cast<Any::Holder<ValueType>*>(content_)->held_;
} else {
return ValueType();
}
}
protected:
class PlaceHolder {
public:
virtual ~PlaceHolder() {}
public:
virtual const std::type_info& GetType() const = 0;
virtual PlaceHolder* clone() const = 0;
};
template <typename ValueType>
class Holder : public PlaceHolder {
public:
explicit Holder(const ValueType& value) : held_(value) {}
virtual const std::type_info& GetType() const { return typeid(ValueType); }
virtual PlaceHolder* clone() const { return new Holder(held_); }
ValueType held_;
};
protected:
PlaceHolder* content_;
template <typename ValueType>
friend ValueType* any_cast(Any*);
};
template <typename ValueType>
ValueType* any_cast(Any* any) {
if (any && any->GetType() == typeid(ValueType)) {
return &(static_cast<Any::Holder<ValueType>*>(any->content_)->held_);
}
return nullptr;
}
template <typename ValueType>
const ValueType* any_cast(const Any* any) {
return any_cast<ValueType>(const_cast<Any*>(any));
}
template <typename ValueType>
ValueType any_cast(const Any& any) {
const ValueType* result = any_cast<ValueType>(&any);
assert(result);
if (!result) {
return ValueType();
}
return *result;
}
} // namespace tubemq
#endif /* TUBEMQ_CLIENT_CPP_SRC_ANY_H_ */