I needed a boost.any lookalike, that could handle a std::unique_ptr. I came up with this. Please provide some c++11 criticism.
#ifndef ANY_HPP
# define ANY_HPP
#include <algorithm>
#include <cassert>
#include <stdexcept>
#include <typeinfo>
#include <type_traits>
#include <utility>
class any
{
public:
any() : content(0) { }
any(any const& other)
: content(other.content ? other.content->clone() : 0)
{
}
any(any&& other) : content(other.content) { other.content = 0; }
template<typename ValueType>
any(ValueType&& value)
: content(new holder<typename std::remove_reference<ValueType>::type>(
std::forward<ValueType>(value)))
{
}
~any() { delete content; }
public: // modifiers
void swap(any& rhs) { std::swap(content, rhs.content); }
any& operator=(any const& rhs)
{
any(rhs).swap(*this);
return *this;
}
any& operator=(any&& rhs)
{
swap(rhs);
return *this;
}
template<typename ValueType>
any& operator=(ValueType&& rhs)
{
any(std::forward<ValueType>(rhs)).swap(*this);
return *this;
}
public: // queries
explicit operator bool() const { return content; }
std::type_info const& type() const
{
return content ? content->type() : typeid(void);
}
private: // types
struct placeholder
{
placeholder() = default;
placeholder(placeholder const&) = delete;
virtual ~placeholder() { }
virtual placeholder* clone() const = 0;
virtual std::type_info const& type() const = 0;
placeholder& operator=(placeholder const&) = delete;
};
template<typename ValueType, typename = void>
struct holder : public placeholder
{
public: // constructor
template <class T>
holder(T&& value) : held(std::forward<T>(value)) { }
placeholder* clone() const final
{
throw std::invalid_argument(typeid(ValueType).name());
return 0;
}
public: // queries
std::type_info const& type() const { return typeid(ValueType); }
public:
ValueType held;
};
template<typename ValueType>
struct holder<ValueType, typename std::enable_if<
std::is_copy_constructible<ValueType>::value>::type>
: public placeholder
{
public: // constructor
template <class T>
holder(T&& value) : held(std::forward<T>(value)) { }
placeholder* clone() const final { return new holder<ValueType>(held); }
public: // queries
std::type_info const& type() const { return typeid(ValueType); }
public:
ValueType held;
};
private: // representation
template<typename ValueType>
friend ValueType* any_cast(any*);
template<typename ValueType>
friend ValueType* unsafe_any_cast(any *);
placeholder* content;
};
class bad_any_cast : public std::bad_cast
{
public:
char const* what() const throw()
{
return "bad_any_cast: failed conversion using any_cast";
}
};
template<typename ValueType>
inline ValueType* unsafe_any_cast(any* operand)
{
return &static_cast<any::holder<ValueType>*>(operand->content)->held;
}
template<typename ValueType>
inline ValueType const* unsafe_any_cast(any const* operand)
{
return unsafe_any_cast<ValueType>(const_cast<any*>(operand));
}
template<typename ValueType>
inline ValueType* any_cast(any* operand)
{
return operand && operand->type() == typeid(ValueType)
? &static_cast<any::holder<ValueType>*>(operand->content)->held
: 0;
}
template<typename ValueType>
inline ValueType const* any_cast(any const* operand)
{
return any_cast<ValueType>(const_cast<any*>(operand));
}
template<typename ValueType>
inline ValueType any_cast(any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
#ifndef NDEBUG
nonref* result(any_cast<nonref>(&operand));
if (!result)
throw bad_any_cast();
return *result;
#else
return *unsafe_any_cast<nonref>(&operand);
#endif // NDEBUG
}
template<typename ValueType>
inline ValueType any_cast(any const& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
return any_cast<nonref const&>(const_cast<any&>(operand));
}
#endif // ANY_HPP
unique_ptr. Why iscontentnot aunique_ptr? – Konrad Rudolph Sep 2 '12 at 12:05any, just likeboost::any, can store any type. – user1095108 Sep 2 '12 at 22:37placeholder* contentyou can useunique_ptr<placeholder> content. It will make your life much easier. – user1131467 Dec 31 '12 at 12:05