00001
00081 #ifndef VTABLE_H
00082 #define VTABLE_H
00083
00084 #include <vector>
00085 #include <cstddef>
00086
00087 #include <argos3/core/utility/logging/argos_log.h>
00088
00089 namespace argos {
00090
00094 template <typename BASE>
00095 struct STagCounter {
00096 static size_t Count;
00097 };
00101 template <typename BASE>
00102 size_t STagCounter<BASE>::Count(0);
00103
00107 template <typename DERIVED, typename BASE>
00108 struct STagHolder {
00109 static size_t Tag;
00110 };
00111
00115 template <typename DERIVED, typename BASE>
00116 size_t GetTag() {
00117 size_t& unTag = STagHolder<const DERIVED, const BASE>::Tag;
00118 if(unTag == 0) {
00119
00120 ++STagCounter<const BASE>::Count;
00121 unTag = STagCounter<const BASE>::Count;
00122 }
00123 return unTag;
00124 }
00125
00129 template <typename DERIVED, typename BASE>
00130 size_t STagHolder<DERIVED, BASE>::Tag = GetTag<DERIVED, BASE>();
00131
00135 template <typename BASE>
00136 struct EnableVTableFor {
00137 template <typename DERIVED>
00138 size_t GetTagHelper(const DERIVED*) const {
00139 return GetTag<DERIVED, BASE>();
00140 }
00141 };
00142
00146 #define ENABLE_VTABLE() \
00147 virtual size_t GetTag() { \
00148 return GetTagHelper(this); \
00149 }
00150
00154 template <typename CONTEXT, typename BASE, typename FUNCTION>
00155 class CVTable {
00156 public:
00157 template <typename DERIVED>
00158 void Add(FUNCTION t_function) {
00159
00160 size_t unIndex = GetTag<DERIVED, BASE>();
00161
00162 if(unIndex >= m_vecVTable.size()) {
00163
00164
00165
00166
00167
00168 const size_t unBaseTag = GetTag<BASE, BASE>();
00169 FUNCTION tDefaultFunction = 0;
00170 if(unBaseTag < m_vecVTable.size()) {
00171 tDefaultFunction = m_vecVTable[unBaseTag];
00172 }
00173
00174 m_vecVTable.resize(unIndex+1, tDefaultFunction);
00175 }
00176 m_vecVTable[unIndex] = t_function;
00177 }
00178
00179 FUNCTION operator[](size_t un_index) const {
00180 if(un_index >= m_vecVTable.size()) {
00181 un_index = GetTag<BASE, BASE>();
00182 }
00183 return m_vecVTable[un_index];
00184 }
00185
00186 inline size_t Size() const {
00187 return m_vecVTable.size();
00188 }
00189
00190 private:
00191 std::vector<FUNCTION> m_vecVTable;
00192
00193 };
00194
00198 template <typename CONTEXT, typename BASE, typename FUNCTION>
00199 CVTable<CONTEXT, BASE, FUNCTION>& GetVTable() {
00200 static CVTable<CONTEXT, BASE, FUNCTION> cVTable;
00201 return cVTable;
00202 }
00203
00204 #define INIT_VTABLE_FOR(BASE) \
00205 struct SVTableInitializerFor ## BASE { \
00206 SVTableInitializerFor ## BASE() { \
00207 GetTag<BASE, BASE>(); \
00208 } \
00209 } sVTableInitializerFor ## BASE;
00210
00211 }
00212
00213 #endif