File: Attribute.h

package info (click to toggle)
mygui 3.4.3%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 38,792 kB
  • sloc: cpp: 133,849; ansic: 30,249; xml: 15,794; cs: 12,601; tcl: 776; python: 400; makefile: 35; sh: 4
file content (131 lines) | stat: -rw-r--r-- 3,697 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*!
	@file
	@author		Albert Semenov
	@date		10/2009
	@module
*/

#ifndef ATTRIBUTE_H_
#define ATTRIBUTE_H_

namespace attribute
{

	// класс обертка для удаления данных из статического вектора
	template<typename Type>
	struct DataHolder
	{
		~DataHolder()
		{
			for (typename Type::iterator item = data.begin(); item != data.end(); ++item)
				delete (*item).first;
		}

		Type data;
	};

	// интерфейс для обертки поля
	template<typename OwnerType, typename SetterType>
	struct Field
	{
		virtual ~Field() = default;
		virtual bool set(OwnerType* _target, typename SetterType::BaseValueType* _value) = 0;
		virtual std::string_view getFieldTypeName() const = 0;
	};

	// шаблон для обертки поля
	template<typename OwnerType, typename FieldType, typename SetterType>
	struct FieldHolder : public Field<OwnerType, SetterType>
	{
		FieldHolder(FieldType* OwnerType::*offset) :
			m_offset(offset)
		{
		}
		FieldType* OwnerType::*const m_offset;

		bool set(OwnerType* _target, typename SetterType::BaseValueType* _value) override
		{
			_target->*m_offset = SetterType::template convert<FieldType>(_value);
			return _target->*m_offset != nullptr;
		}
		std::string_view getFieldTypeName() const override
		{
			return FieldType::getClassTypeName();
		}
	};

	// шаблон для атрибута поля
	template<typename OwnerType, typename ValueType, typename SetterType>
	struct AttributeField
	{
		using BindPair = std::pair<Field<OwnerType, SetterType>*, ValueType>;
		using VectorBindPair = std::vector<BindPair>;

		template<typename FieldType>
		AttributeField(FieldType* OwnerType::*_offset, const ValueType& _value)
		{
			getData().push_back(BindPair(new FieldHolder<OwnerType, FieldType, SetterType>(_offset), _value));
		}
		static VectorBindPair& getData()
		{
			static DataHolder<VectorBindPair> data;
			return data.data;
		}
	};

	// макрос для инстансирования атрибута поля
#define DECLARE_ATTRIBUTE_FIELD(_name, _type, _setter) \
	template<typename OwnerType, typename ValueType = _type, typename SetterType = _setter> \
	struct _name : public attribute::AttributeField<OwnerType, ValueType, SetterType> \
	{ \
		template<typename FieldType> \
		_name(FieldType* OwnerType::*_offset, const ValueType& _value) : \
			AttributeField<OwnerType, ValueType, SetterType>(_offset, _value) \
		{ \
		} \
	}

	// макрос для инстансирования экземпляра атрибута
#define ATTRIBUTE_FIELD(_attribute, _class, _field, _value) \
	struct _attribute##_##_field \
	{ \
		_attribute##_##_field() \
		{ \
			static attribute::_attribute<_class> bind(&_class::_field, _value); \
		} \
	} _attribute##_##_field


	// шаблон для атрибута класса
	template<typename Type, typename ValueType>
	struct ClassAttribute
	{
		ClassAttribute(const ValueType& _value)
		{
			getData() = _value;
		}
		static ValueType& getData()
		{
			static ValueType data;
			return data;
		}
	};

	// макрос для инстансирования атрибута класса
#define DECLARE_ATTRIBUTE_CLASS(_name, _type) \
	template<typename Type, typename ValueType = _type> \
	struct _name : public attribute::ClassAttribute<_name<Type>, ValueType> \
	{ \
		_name(const ValueType& _value) : \
			ClassAttribute<_name<Type>, ValueType>(_value) \
		{ \
		} \
	}

	// макрос для инстансирования экземпляра класса
#define ATTRIBUTE_CLASS(_attribute, _class, _value) \
	class _class; \
	static attribute::_attribute<_class> _attribute##_##_class(_value)
}

#endif // ATTRIBUTE_H_