a standard experimental class any
This commit is contained in:
@@ -1,145 +1,159 @@
|
||||
/**
|
||||
* Any
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file nana/any.hpp
|
||||
*
|
||||
* @brief An implementation of experimental library any of C++ standard(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html#any)
|
||||
*/
|
||||
|
||||
#ifndef NANA_ANY_HPP
|
||||
#define NANA_ANY_HPP
|
||||
#include <typeinfo>
|
||||
#include <utility> //C++11 for std::move
|
||||
#include <type_traits>
|
||||
|
||||
#include "c++defines.hpp"
|
||||
|
||||
namespace nana
|
||||
{
|
||||
|
||||
class bad_any_cast
|
||||
: public std::bad_cast
|
||||
{
|
||||
};
|
||||
|
||||
class any
|
||||
{
|
||||
struct super_type
|
||||
class content_interface
|
||||
{
|
||||
virtual ~super_type();
|
||||
super_type& operator=(const super_type&);
|
||||
virtual super_type& assign(const super_type&) = 0;
|
||||
virtual bool same(const super_type&) const = 0;
|
||||
virtual super_type* clone() const = 0;
|
||||
}; //end struct super_type
|
||||
|
||||
template<typename T>
|
||||
struct object_type
|
||||
: public super_type
|
||||
{
|
||||
object_type(){}
|
||||
public:
|
||||
virtual ~content_interface() = default;
|
||||
|
||||
object_type(T const & obj)
|
||||
: object(obj)
|
||||
virtual const std::type_info& type() const noexcept = 0;
|
||||
virtual content_interface* clone() const = 0;
|
||||
};
|
||||
|
||||
template<typename Value>
|
||||
class holder : public content_interface
|
||||
{
|
||||
holder& operator=(const holder&) = delete;
|
||||
public:
|
||||
holder(const Value& other)
|
||||
: value(other)
|
||||
{}
|
||||
|
||||
object_type(T && obj)
|
||||
: object(std::move(obj))
|
||||
holder(Value&& other)
|
||||
: value(static_cast<Value&&>(other))
|
||||
{}
|
||||
|
||||
object_type(const object_type& rhs)
|
||||
:object(rhs.object)
|
||||
{}
|
||||
|
||||
virtual super_type& assign(const super_type& rhs)
|
||||
public:
|
||||
const std::type_info& type() const noexcept override
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
auto other = dynamic_cast<const object_type*>(&rhs);
|
||||
if(other)
|
||||
object = other->object;
|
||||
}
|
||||
return *this;
|
||||
return typeid(Value);
|
||||
}
|
||||
|
||||
virtual bool same(const super_type& rhs) const
|
||||
|
||||
content_interface* clone() const override
|
||||
{
|
||||
return (dynamic_cast<const object_type*>(&rhs) != nullptr);
|
||||
return new holder(value);
|
||||
}
|
||||
|
||||
virtual super_type* clone() const
|
||||
{
|
||||
return new object_type(object);
|
||||
}
|
||||
|
||||
T object;
|
||||
}; //end struct object_type
|
||||
public:
|
||||
Value value; //representation accessable for friend of any
|
||||
};
|
||||
public:
|
||||
template<typename T>
|
||||
any(const T & obj)
|
||||
: super_(new object_type<typename std::remove_reference<T>::type>(obj))
|
||||
{}
|
||||
//constructors and destructor
|
||||
any() noexcept;
|
||||
|
||||
template<typename T>
|
||||
any(T && obj)
|
||||
: super_(new object_type<typename std::remove_reference<T>::type>(std::move(obj)))
|
||||
{}
|
||||
any(const any& other);
|
||||
any(any&& other) noexcept;
|
||||
|
||||
template<typename Value>
|
||||
any(Value && value,
|
||||
typename std::enable_if<!std::is_same<any&, Value>::value>::type * = nullptr,
|
||||
typename std::enable_if<!std::is_const<Value>::value>::type* = nullptr)
|
||||
: content_(new holder<typename std::decay<Value>::type>(static_cast<Value&&>(value)))
|
||||
{
|
||||
}
|
||||
|
||||
any();
|
||||
any(const any&);
|
||||
any(any&&);
|
||||
~any();
|
||||
|
||||
bool same(const any &) const;
|
||||
any& operator=(const any&);
|
||||
any& operator=(any&&);
|
||||
|
||||
template<typename T>
|
||||
any& operator=(T const &rhs)
|
||||
|
||||
//assignments
|
||||
any& operator=(const any& other);
|
||||
any& operator=(any&& other) noexcept;
|
||||
|
||||
template<class Value>
|
||||
any& operator=(Value&& other)
|
||||
{
|
||||
T * obj = get<T>();
|
||||
if(nullptr == obj)
|
||||
{
|
||||
delete super_;
|
||||
super_ = new object_type<T>(rhs);
|
||||
}
|
||||
else
|
||||
*obj = rhs;
|
||||
any(other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
any & operator=(T && rhs)
|
||||
{
|
||||
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
|
||||
type* obj = get<type>();
|
||||
if(nullptr == obj)
|
||||
{
|
||||
delete super_;
|
||||
super_ = new object_type<type>(std::move(rhs));
|
||||
}
|
||||
else
|
||||
*obj = std::move(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T * get() const
|
||||
{
|
||||
if(super_)
|
||||
{
|
||||
typedef typename std::remove_const<T>::type type;
|
||||
object_type<type>* obj = dynamic_cast<object_type<type>*>(super_);
|
||||
if(obj) return &(obj->object);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
operator T&() const
|
||||
{
|
||||
typedef typename std::remove_const<T>::type type;
|
||||
type *obj = get<type>();
|
||||
//modifiers
|
||||
void clear() noexcept;
|
||||
void swap(any& other) noexcept;
|
||||
|
||||
if(nullptr == obj)
|
||||
throw std::bad_cast();
|
||||
|
||||
return *obj;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
operator T*() const
|
||||
{
|
||||
typedef typename std::remove_const<T>::type type;
|
||||
return get<type>();
|
||||
}
|
||||
//observers
|
||||
bool empty() const noexcept;
|
||||
const std::type_info& type() const noexcept;
|
||||
private:
|
||||
super_type * super_;
|
||||
template<typename Value>
|
||||
friend Value* any_cast(any*) noexcept;
|
||||
private:
|
||||
content_interface * content_;
|
||||
};
|
||||
|
||||
// Non-member functions
|
||||
inline void swap(any& x, any& y) noexcept
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
Value any_cast(const any& operand)
|
||||
{
|
||||
using value_type = typename std::remove_reference<Value>::type;
|
||||
return any_cast<const value_type&>(const_cast<any&>(operand));
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
Value any_cast(any& operand)
|
||||
{
|
||||
using value_type = typename std::remove_reference<Value>::type;
|
||||
|
||||
auto value_ptr = any_cast<value_type>(&operand);
|
||||
if (!value_ptr)
|
||||
throw bad_any_cast();
|
||||
|
||||
using ref_type = typename std::conditional<std::is_reference<Value>::value, Value, typename std::add_lvalue_reference<Value>::type>::type;
|
||||
return static_cast<ref_type>(*value_ptr);
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
Value any_cast(any && operand)
|
||||
{
|
||||
static_assert(std::is_rvalue_reference<Value&&>::value || std::is_const<typename ::std::remove_reference<Value>::type>::value, "nana::any_cast shall not be used for getting non-const reference to temporary objects");
|
||||
return any_cast<Value>(operand);
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
const Value* any_cast(const any* operand) noexcept
|
||||
{
|
||||
return any_cast<Value>(const_cast<any*>(operand));
|
||||
}
|
||||
|
||||
template<typename Value>
|
||||
Value* any_cast(any* operand) noexcept
|
||||
{
|
||||
if (!operand)
|
||||
return nullptr;
|
||||
|
||||
auto holder = dynamic_cast<any::holder<Value>*>(operand->content_);
|
||||
return (holder ? &holder->value : nullptr);
|
||||
}
|
||||
|
||||
}//end namespace nana
|
||||
|
||||
#endif
|
||||
|
||||
@@ -43,6 +43,21 @@
|
||||
#ifndef NANA_CXX_DEFINES_INCLUDED
|
||||
#define NANA_CXX_DEFINES_INCLUDED
|
||||
|
||||
//C++ language
|
||||
#if defined(_MSC_VER)
|
||||
# if (_MSC_VER < 1900)
|
||||
# //Nana defines some macros for lack of support of keywords
|
||||
# define _ALLOW_KEYWORD_MACROS
|
||||
#
|
||||
# define noexcept //no support of noexcept until Visual C++ 2015
|
||||
# define constexpr //no support of constexpr until Visual C++ 2015
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
|
||||
# define noexcept //no support of noexcept until GCC 4.6
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Select platform ......
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) //Microsoft Windows
|
||||
#define NANA_WINDOWS
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Concepts Definition of Nana C++ Library
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -22,7 +22,7 @@ namespace nana
|
||||
class any_objective
|
||||
{
|
||||
public:
|
||||
virtual ~any_objective(){}
|
||||
virtual ~any_objective() = default;
|
||||
|
||||
template<typename Target>
|
||||
void anyobj(const Target& t)
|
||||
@@ -37,7 +37,7 @@ namespace nana
|
||||
void anyobj(Target&& t)
|
||||
{
|
||||
nana::any * p = _m_anyobj(true);
|
||||
if(nullptr == 0)
|
||||
if(nullptr == p)
|
||||
throw std::runtime_error("Nana.any_objective: Object does not exist");
|
||||
|
||||
*p = std::move(t);
|
||||
@@ -46,8 +46,7 @@ namespace nana
|
||||
template<typename Target>
|
||||
Target * anyobj() const ///< Retrieves the attached object. Returns a nullptr if empty or if the type not match.
|
||||
{
|
||||
nana::any * p = _m_anyobj(false);
|
||||
return (p ? p->get<Target>() : nullptr);
|
||||
return any_cast<Target>(_m_anyobj(false));
|
||||
}
|
||||
private:
|
||||
virtual nana::any* _m_anyobj(bool allocate_if_empty) const = 0;
|
||||
@@ -60,7 +59,7 @@ namespace nana
|
||||
public:
|
||||
typedef IndexType anyobj_index_t; ///< The type of index. It is available if Dimension is greater than 0.
|
||||
|
||||
virtual ~any_objective(){}
|
||||
virtual ~any_objective() = default;
|
||||
|
||||
template<typename Target>
|
||||
void anyobj(anyobj_index_t i, const Target& t)
|
||||
@@ -83,8 +82,7 @@ namespace nana
|
||||
template<typename Target>
|
||||
Target * anyobj(anyobj_index_t i) const ///< Retrieves the attached object. Returns a nullptr if empty or if the type not match.
|
||||
{
|
||||
nana::any * p = _m_anyobj(i, false);
|
||||
return (p ? p->get<Target>() : nullptr);
|
||||
return any_cast<Target>(_m_anyobj(i, false));
|
||||
}
|
||||
private:
|
||||
virtual nana::any* _m_anyobj(anyobj_index_t i, bool allocate_if_empty) const = 0;
|
||||
@@ -121,8 +119,7 @@ namespace nana
|
||||
template<typename Target>
|
||||
Target * anyobj(anyobj_index_t i0, anyobj_index_t i1) const ///< Retrieves the attached object. Returns a nullptr if empty or if the type not match.
|
||||
{
|
||||
nana::any * p = _m_anyobj(i0, i1, false);
|
||||
return (p ? p->get<Target>() : nullptr);
|
||||
return any_cast<Target>(_m_anyobj(i0, i1, false));
|
||||
}
|
||||
private:
|
||||
virtual nana::any* _m_anyobj(anyobj_index_t i0, anyobj_index_t i1, bool allocate_if_empty) const = 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Platform Specification Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -34,7 +34,9 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "msg_packet.hpp"
|
||||
#if defined(NANA_UNICODE)
|
||||
|
||||
#define NANA_USE_XFT
|
||||
#if defined(NANA_USE_XFT)
|
||||
#include <X11/Xft/Xft.h>
|
||||
#include <iconv.h>
|
||||
#include <fstream>
|
||||
@@ -45,7 +47,7 @@ namespace nana
|
||||
namespace detail
|
||||
{
|
||||
class msg_dispatcher;
|
||||
#if defined(NANA_UNICODE)
|
||||
#if defined(NANA_USE_XFT)
|
||||
class conf
|
||||
{
|
||||
public:
|
||||
@@ -76,7 +78,7 @@ namespace detail
|
||||
bool italic;
|
||||
bool underline;
|
||||
bool strikeout;
|
||||
#if defined(NANA_UNICODE)
|
||||
#if defined(NANA_USE_XFT)
|
||||
XftFont * handle;
|
||||
#else
|
||||
XFontSet handle;
|
||||
@@ -99,7 +101,7 @@ namespace detail
|
||||
unsigned tab_pixels;
|
||||
unsigned whitespace_pixels;
|
||||
}string;
|
||||
#if defined(NANA_UNICODE)
|
||||
#if defined(NANA_USE_XFT)
|
||||
XftDraw * xftdraw{nullptr};
|
||||
XftColor xft_fgcolor;
|
||||
const std::string charset(const std::wstring& str, const std::string& strcode);
|
||||
@@ -120,7 +122,7 @@ namespace detail
|
||||
unsigned color_{ 0xFFFFFFFF };
|
||||
unsigned text_color_{ 0xFFFFFFFF };
|
||||
|
||||
#if defined(NANA_UNICODE)
|
||||
#if defined(NANA_USE_XFT)
|
||||
struct conv_tag
|
||||
{
|
||||
iconv_t handle;
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace nana
|
||||
|
||||
void selected(::nana::any & var)
|
||||
{
|
||||
auto vp = var.get<T>();
|
||||
auto vp = any_cast<T>(&var);
|
||||
|
||||
T null_val;
|
||||
arg_categorize<T> arg(widget_, vp ? *vp : null_val);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Combox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -85,8 +85,7 @@ namespace nana
|
||||
template<typename T>
|
||||
T * value_ptr() const
|
||||
{
|
||||
auto p = _m_anyobj(false);
|
||||
return (p ? p->get<T>() : nullptr);
|
||||
return any_cast<T>(_m_anyobj(false));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -96,7 +95,7 @@ namespace nana
|
||||
if (nullptr == pany)
|
||||
throw std::runtime_error("combox::item_proxy.value<T>() is empty");
|
||||
|
||||
T * p = pany->get<T>();
|
||||
T * p = any_cast<T>(pany);
|
||||
if (nullptr == p)
|
||||
throw std::runtime_error("combox::item_proxy.value<T>() invalid type of value");
|
||||
return *p;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A List Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -277,8 +277,7 @@ namespace nana
|
||||
template<typename T>
|
||||
T* value_ptr() const
|
||||
{
|
||||
auto * pany = _m_value();
|
||||
return (pany ? pany->get<T>() : nullptr);
|
||||
return any_cast<T>(_m_value());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -288,7 +287,7 @@ namespace nana
|
||||
if(nullptr == pany)
|
||||
throw std::runtime_error("listbox::item_proxy.value<T>() is empty");
|
||||
|
||||
T * p = pany->get<T>();
|
||||
T * p = any_cast<T>(_m_value());
|
||||
if(nullptr == p)
|
||||
throw std::runtime_error("listbox::item_proxy.value<T>() invalid type of value");
|
||||
return *p;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Tabbar implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -222,7 +222,7 @@ namespace nana
|
||||
|
||||
value_type & operator[](std::size_t pos) const
|
||||
{
|
||||
return static_cast<value_type&>(this->get_drawer_trigger().at_no_bound_check(pos));
|
||||
return any_cast<value_type&>(this->get_drawer_trigger().at_no_bound_check(pos));
|
||||
}
|
||||
|
||||
void activated(std::size_t pos) /// Activates a tab specified by pos.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Tree Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -288,15 +288,15 @@ namespace nana
|
||||
bool operator!=(const item_proxy&) const;
|
||||
|
||||
template<typename T>
|
||||
T * value_ptr() const
|
||||
const T * value_ptr() const
|
||||
{
|
||||
return _m_value().get<T>();
|
||||
return any_cast<T>(&_m_value());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& value() const
|
||||
const T& value() const
|
||||
{
|
||||
T* p = _m_value().get<T>();
|
||||
auto p = any_cast<T>(&_m_value());
|
||||
if(nullptr == p)
|
||||
throw std::runtime_error("treebox::value<T>() Invalid type of value.");
|
||||
return *p;
|
||||
|
||||
Reference in New Issue
Block a user