Created
April 4, 2016 15:42
-
-
Save sholsapp/c38d68e8e4b199fa7124ca1305d23267 to your computer and use it in GitHub Desktop.
An implementation of a boost::any-like thing.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <map> | |
#include <string> | |
#include <utility> | |
class any { | |
public: | |
any() | |
: content(0) | |
{} | |
any(const any &other) | |
: content(other.content ? other.content->clone() : 0) | |
{} | |
template<typename value_type> | |
any(const value_type &value) | |
: content(new holder<value_type>(value)) | |
{} | |
any &swap(any &rhs) { | |
std::swap(content, rhs.content); | |
return *this; | |
} | |
any &operator=(const any &rhs) { | |
// TODO(sholsapp): WTF | |
any tmp = any(rhs); | |
return swap(tmp); | |
} | |
template<typename value_type> | |
any &operator=(const value_type &rhs) { | |
// TODO(sholsapp): WTF | |
any tmp = any(rhs); | |
return swap(tmp); | |
} | |
~any() { | |
delete content; | |
} | |
const std::type_info &type_info() const { | |
return content | |
? content->type_info() | |
: typeid(void); | |
} | |
operator const void *() const { | |
return content; | |
} | |
template<typename value_type> | |
bool copy_to(value_type &value) const { | |
const value_type *copyable = to_ptr<value_type>(); | |
if (copyable) | |
value = *copyable; | |
return copyable; | |
} | |
template<typename value_type> | |
const value_type *to_ptr() const { | |
return type_info() == typeid(value_type) | |
? std::addressof(static_cast<holder<value_type> *>(content)->held) | |
: 0; | |
} | |
private: | |
class placeholder { | |
public: | |
virtual ~placeholder() {} | |
virtual const std::type_info &type_info() const = 0; | |
virtual placeholder *clone() const = 0; | |
}; | |
template <typename value_type> | |
class holder: public placeholder { | |
public: | |
holder(const value_type &value) | |
: held(value) | |
{} | |
virtual const std::type_info &type_info() const { | |
return typeid(value_type); | |
} | |
virtual placeholder *clone() const { | |
return new holder(held); | |
} | |
const value_type held; | |
}; | |
placeholder *content; | |
}; | |
template<typename value_type> | |
value_type any_cast(const any &operand) { | |
const value_type *result = operand.to_ptr<value_type>(); | |
return result | |
? *result | |
: throw std::bad_cast(); | |
} | |
int main(int argc, char *argv[]) { | |
std::map<std::string, any> test; | |
test["integer"] = static_cast<int64_t>(1); | |
test["string"] = std::string("foo"); | |
test["float"] = 3.14; | |
int64_t a_integer = any_cast<int64_t>(test["integer"]); | |
std::string a_string = any_cast<std::string>(test["string"]); | |
double a_float = any_cast<double>(test["float"]); | |
std::cout << "test[\"integer\"] = " << a_integer << std::endl | |
<< "test[\"string\"] = " << a_string << std::endl | |
<< "test[\"float\"] = " << a_float << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment