前几天看到一个网络库中有boost::any类型的变量,后来搜索了一下发现挺有意思的,看到了这篇博客:
http://blog.youkuaiyun.com/mfcing/article/details/44705831 boost::any的扩展和使用。这位老兄讲的很好,还给出了一个简易的实现版本,我在之基础上做了一些扩展,当然也是个简易版本。本代码中的各种构造函数都有printf标记,以供观察调用流程。最后附有test代码。
不知道为什么格式变得如此诡异。。。这个版本主要是加入了移动语义,写的时候也遇到了很多典型的问题,好在在《Effective Modern C++》这本书中找到了答案。比如很典型的overloading on universal references。以及如何解决universal references匹配性过强的问题等等,总的来说带着问题翻阅这类书籍会给我留下很深的印象。
当然,如果你发现了任何不完善的地方或者bug,欢迎留言。
#pragma once
#include<algorithm>
#include<exception>
#include<utility>
#include<iostream>
namespace myany {
class any final {
protected:
class base {
public:
virtual void* getValue() = 0;
virtual const char *getClassName() = 0 ;
virtual base *clone() = 0;
};
template<typename TypeName>
class CValue : public base {
private:
TypeName value_;
public:
CValue(const TypeName& val) : value_((val)) { std::cout << "cvalue copy constructor !\n"; }
CValue(TypeName&& val) : value_(std::move(val)) { std::cout << "cvalue move constructor !\n"; }
virtual void *getValue() {
return &value_;
}
virtual const char *getClassName() {
return typeid(TypeName).name();
}
virtual base *clone() {
std::cout << "cvalue func:clone !\n";
return new CValue<TypeName>(value_);
}
};
public:
any() :value_(nullptr) { std::cout << "any default constructor !\n"; }
bool isEmpty() const {
return value_ == nullptr;
}
template<typename T,typename =
typename std::enable_if<
!std::is_same<
any,typename std::decay<T>::type
>::value
>::type
>
explicit any(T&& t) : value_(new CValue<typename std::decay<T>::type>(t)) { std::cout << "any univeral template !\n"; }
any(const any& ma) :value_(ma.isEmpty() ? nullptr : ma.value_->clone()) { std::cout << "any copy constructor !\n"; }
any(any&& ma) :value_(ma.isEmpty() ? nullptr : ma.value_) {
ma.value_ = nullptr;
std::cout << "any move constructor !\n";
}
virtual ~any() {
if (value_) {
delete value_;
}
}
any& swap(any& ma) {
std::swap(ma.value_, value_);
return *this;
}
template<typename T>
any& operator=(T&& val) {
any(std::forward<T>(val)).swap(*this);
std::cout << "any operator= !\n";
return *this;
}
const char *type() {
if (value_ == nullptr) {
return nullptr;
}
return value_->getClassName();
}
base *getValue() {
return value_;
}
private:
base * value_;
};
template<typename T>
T *any_cast(any *ma) {
if (typeid(T).name() == ma->getValue()->getClassName()) {
return reinterpret_cast<T*>(ma->getValue()->getValue());
}
else
throw std::runtime_error("bad_any_cast");
}
template<typename T>
T& any_cast(any &ma) {
if (typeid(T).name() == ma.getValue()->getClassName()) {
return *reinterpret_cast<T*>(ma.getValue()->getValue());
}
else
throw std::runtime_error("bad_any_cast");
}
}//namespace myany
#include "any.h"
#include<utility>
#include<string>
int main() {
myany::any test;
myany::any test2(2.3);
test = std::string("hello");
const int num = 5;
test = num;
test = std::move(test2);
myany::any test3;
test3 = test;
system("pause");
return 0;
}