C++11实现的Boost库中的Any类

/******************************************************************************

*

*  Permission is hereby granted, free of charge, to any person obtaining a copy

*  of this software and associated documentation files (the "Software"), to deal

*  in the Software without restriction, including without limitation the rights

*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

*  copies of the Software, and to permit persons to whom the Software is

*  furnished to do so, subject to the following conditions:

*

*  The above copyright notice and this permission notice shall be included in

*  all copies or substantial portions of the Software.

*

*  Author:Zheng Fasheng

*

*  Email:zheng_fasheng@outlook.com

*

*  Date:2016/9/4 20:55

*

*  Summary:Declares any class from the boost library

******************************************************************************/

#pragma once

#include <exception>

#include <typeinfo>

#include <type_traits>

#include <typeindex>

#include <string>

namespace detail{

template <bool B, class T = void>

struct disable_if_c {

typedef T type;

};

template <class T>

struct disable_if_c<true, T> {};

template <class Cond, class T = void>

struct disable_if : public disable_if_c<Cond::value, T> {};

template<bool,class _Ty1,class _Ty2>

struct _If

{ // type is _Ty2 for assumed false

typedef _Ty2 type;

};

template<class _Ty1,class _Ty2>

struct _If<true, _Ty1, _Ty2>

{ // type is _Ty1 for assumed true

typedef _Ty1 type;

};

template<class _Ty>

struct add_reference

{ // add reference

typedef typename std::remove_reference<_Ty>::type& type;

};

template<>

struct add_reference<void>

{ // add reference

typedef void type;

};

template<>

struct add_reference<const void>

{ // add reference

typedef const void type;

};

template<>

struct add_reference<volatile void>

{ // add reference

typedef volatile void type;

};

template<>

struct add_reference<const volatile void>

{ // add reference

typedef const volatile void type;

};

class bad_cast{

public:

explicit bad_cast(const std::string& msg ){

_what = msg;

}

const char* what() const{

return _what.data();

};

private:

std::string _what;

};

}

class Any

{

public:

Any()

: content(0)

{

}

template<typename _Ty>

Any(const _Ty & value)

: content(new holder<typename std::remove_cv< typename std::decay<const _Ty>::type>::type>(value))

{

}

Any(const Any & other)

: content(other.content ? other.content->clone() : 0)

{

}

//c++11

// Move constructor

Any(Any&& other)

: content(other.content)

{

other.content = 0;

}

// Perfect forwarding of ValueType

template<typename _Ty>

Any(_Ty&& value

, typename detail::disable_if< typename std::is_same<Any&, _Ty> >::type* = 0 // disable if value has type `any&`

, typename detail::disable_if< typename std::is_const<_Ty> >::type* = 0) // disable if value has type `const ValueType&&`

: content(new holder< typename std::decay<_Ty>::type >(static_cast<_Ty&&>(value)))

{

}

~Any()

{

if (content)

{

delete content;

}

content = nullptr;

}

public:

Any& swap(Any& rhs)

{

std::swap(content, rhs.content);

return *this;

}

Any& operator=(const Any& rhs)

{

Any(rhs).swap(*this);

return *this;

}

//c++11

//move assignement

Any& operator=(Any&& rhs)

{

rhs.swap(*this);

Any().swap(rhs);

return *this;

}

//perfect forwarding of valueType

template<class valueType>

Any& operator=(valueType&& rhs)

{

Any(static_cast<valueType&&>(rhs)).swap(*this);

return *this;

}

public: // queries

bool empty()

{

return !content;

}

void clear()

{

Any().swap(*this);

}

const std::type_info& type() const

{

return content ? content->type() : typeid(void);

}

private:

class placeholder

{

public:

virtual ~placeholder(){}

virtual const std::type_info& type() const = 0;

virtual placeholder* clone() const = 0;

};

template<typename _Ty>

class holder : public placeholder

{

public:

typedef _Ty value_type;

holder(const _Ty& value) :held(value){}

holder(_Ty&& value)

:held(static_cast<_Ty&&>(value))

{

}

virtual const std::type_info& type() const

{

return typeid(value_type);

}

virtual placeholder* clone() const

{

return new holder(held);

}

public:

_Ty held;

private:

// intentionally left unimplemented

holder& operator=(const holder &);

};

private: // representation

template<typename _Ty>

friend _Ty * any_cast(Any *);

template<typename _Ty>

friend _Ty * unsafe_any_cast(Any *);

private:

placeholder* content;

};

inline void swap(Any & lhs, Any & rhs)

{

lhs.swap(rhs);

}

template<typename _Ty>

_Ty * any_cast(Any * operand)

{

return operand && operand->type() == typeid(_Ty)

? &static_cast<Any::holder< typename std::remove_cv<_Ty>::type> *>(operand->content)->held

: 0;

}

template<typename _Ty>

inline const _Ty * any_cast(const Any * operand)

{

return any_cast<_Ty>(const_cast<Any *>(operand));

}

template<typename _Ty>

_Ty any_cast(Any & operand)

{

typedef typename std::remove_reference<_Ty>::type nonref;

nonref * result = any_cast<nonref>(&operand);

if (!result)

{

std::string szReason = "bad any_cast : can't convert ";

szReason += operand.type().name();

szReason += " to ";

szReason += typeid(_Ty).name();

throw detail::bad_cast(szReason);

}

// Attempt to avoid construction of a temporary object in cases when

// `ValueType` is not a reference. Example:

// `static_cast<std::string>(*result);`

// which is equal to `std::string(*result);`

typedef typename detail::_If<

std::is_reference<_Ty>::value,

_Ty,

typename detail::add_reference<_Ty>::type

>::type ref_type;

return static_cast<ref_type>(*result);

}

template<typename _Ty>

inline _Ty any_cast(const Any & operand)

{

typedef typename std::remove_reference<_Ty>::type nonref;

return any_cast<const nonref &>(const_cast<Any &>(operand));

}

template<typename _Ty>

inline _Ty any_cast(Any&& operand)

{

static_assert(

std::is_rvalue_reference<_Ty&&>::value /*true if ValueType is rvalue or just a value*/

|| std::is_const< typename std::remove_reference<_Ty>::type >::value,

"any_cast shall not be used for getting nonconst references to temporary objects"

);

return any_cast<_Ty>(operand);

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容

  • 接着上节 condition_varible ,本节主要介绍future的内容,练习代码地址。本文参考http:/...
    jorion阅读 14,746评论 1 5
  • 再读高效c++,颇有收获,现将高效c++中的经典分享如下,希望对你有所帮助。 1、尽量以const \enum\i...
    橙小汁阅读 1,202评论 0 1
  • 这里把STL里处理iterator的tag-dispatching + trait class机制提取一点出来并浅...
    Quasars阅读 518评论 0 1
  • 【转载】原文地址:std::string详解作者:kieven2008 之所以抛弃char*的字符串而选用C++标...
    VAYY阅读 635评论 0 2
  • 不讲语言特性,只从工程角度出发,个人觉得C++标准委员会在C++11中对多线程库的引入是有史以来做得最人道的一件事...
    stidio阅读 13,232评论 0 11