├── .gitignore ├── LICENSE ├── README.md └── include └── dbpp ├── database.hpp ├── dbpp.hpp ├── field.hpp ├── id.hpp ├── meta ├── type_list.hpp └── utility.hpp ├── record.hpp └── typestring.hh /.gitignore: -------------------------------------------------------------------------------- 1 | # KDE related files that are automatically created 2 | .directory 3 | */.directory 4 | *.kdev4 5 | 6 | # Compiled Object files 7 | *.slo 8 | *.lo 9 | *.o 10 | *.obj 11 | 12 | # Precompiled Headers 13 | *.gch 14 | *.pch 15 | 16 | # Compiled Dynamic libraries 17 | *.so 18 | *.dylib 19 | *.dll 20 | 21 | # Fortran module files 22 | *.mod 23 | *.smod 24 | 25 | # Compiled Static libraries 26 | *.lai 27 | *.la 28 | *.a 29 | *.lib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | 36 | # Files to do with testing 37 | build 38 | test 39 | CMakeLists.txt 40 | */CMakeLists.txt 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016, Keith Hammond 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dbpp 2 | ---- 3 | 4 | ## About 5 | 6 | A generic, header-only C++14 database library. Store any values that are default-initializable, copy-assignable and move-assignable. 7 | 8 | Makes heavy use of compile-time strings so records/fields are easily accessible at compile-time. 9 | 10 | All the code is documented for doxygen, so running doxygen on the include directory should be sufficent if you want better documentation. 11 | 12 | ## Credit where due 13 | 14 | I'm using this great [compile-time string library](https://github.com/irrequietus/typestring) from [George Makrydakis](https://github.com/irrequietus) to achieve compile-time string identifiers. 15 | 16 | ## Example 17 | 18 | Here is an example of a user information database 19 | ```c++ 20 | #include "dbpp/dbpp.hpp" 21 | 22 | int main(){ 23 | using user_record = dbpp::record< 24 | // the id of the record is "users" 25 | dbpp_id("users"), 26 | 27 | // the type used to identify individual instances of this record 28 | std::string, 29 | 30 | // some fields 31 | dbpp::field, 32 | dbpp::field 33 | >; 34 | 35 | // database with one type of record 36 | dbpp::database db; 37 | 38 | // get record category by id 39 | auto &&users = db.get(); 40 | 41 | // create a user record 42 | auto &&coolUserName420 = users.make_record("coolUserName420", "skuxx_muffin70@gmail.com"); 43 | 44 | // we need to modify the users email 45 | coolUserName420.get() = "skuxx_muffin69@gmail.com"; 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /include/dbpp/database.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DBPP_DATABASE_HPP 2 | #define DBPP_DATABASE_HPP 1 3 | 4 | #include 5 | 6 | #include "meta/utility.hpp" 7 | #include "record.hpp" 8 | 9 | namespace dbpp{ 10 | /** 11 | * class to hold values of a type of record 12 | * 13 | * @tparam Record the type of record to hold values of 14 | **/ 15 | template 16 | class record_holder{ // olympic class, mind you 17 | public: 18 | using id_type = typename Record::id_type; 19 | 20 | /** 21 | * create a record in the holder 22 | * 23 | * @param[in] id_ the id of the new record 24 | * @param[in,out] field_args arguments to pass individually to each of the record fields e.g. field(field_args)... 25 | **/ 26 | template 27 | decltype(auto) make_record(id_type id_, FieldArgs &&... field_args){ 28 | { 29 | auto res = m_map.find(id_); 30 | if(res != std::end(m_map)) 31 | throw std::runtime_error{"record already exists"}; 32 | } 33 | 34 | auto res = m_map.insert({id_, {std::forward_as_tuple(std::forward(field_args)...)}}); 35 | if(!res.second) 36 | throw std::runtime_error{"error in std::unordered_map::insert"}; 37 | 38 | return res.first->second; 39 | } 40 | 41 | /** 42 | * erase a record from the holder 43 | * 44 | * @param[in] id_ the record id to erase 45 | **/ 46 | void erase_record(id_type id_){ 47 | m_map.erase(id_); 48 | } 49 | 50 | /** 51 | * get a record from the holder 52 | * 53 | * @param[in] id_ the id of the record 54 | **/ 55 | decltype(auto) get_record(id_type id_){ 56 | auto res = m_map.find(id_); 57 | if(res == std::end(m_map)) 58 | throw std::runtime_error{"record doesn't exist"}; 59 | 60 | return *res; 61 | } 62 | 63 | Record &operator [](const id_type &id_){ 64 | return m_map[id_]; 65 | } 66 | 67 | private: 68 | std::unordered_map m_map; 69 | }; 70 | 71 | /** 72 | * a generic database holding any number of record types 73 | * 74 | * @tparam Records the types of record to hold 75 | **/ 76 | template 77 | class database{ 78 | public: 79 | /** 80 | * get a record database by id 81 | * 82 | * @tparam RecordId the id of the record type 83 | **/ 84 | template 85 | decltype(auto) get(){ 86 | return std::get< 87 | record_holder< 88 | meta::get_type_by_id_t< 89 | RecordId, meta::type_list 90 | > 91 | > 92 | >(m_records); 93 | } 94 | 95 | private: 96 | std::tuple...> m_records; 97 | }; 98 | } 99 | 100 | #endif // DBPP_DATABASE_HPP 101 | -------------------------------------------------------------------------------- /include/dbpp/dbpp.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DBPP_DBPP_HPP 2 | #define DBPP_DBPP_HPP 1 3 | 4 | #include "id.hpp" 5 | #include "record.hpp" 6 | #include "field.hpp" 7 | #include "database.hpp" 8 | 9 | #endif // DBPP_DBPP_HPP 10 | -------------------------------------------------------------------------------- /include/dbpp/field.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DBPP_FIELD_HPP 2 | #define DBPP_FIELD_HPP 1 3 | 4 | #include "id.hpp" 5 | 6 | namespace dbpp{ 7 | /** 8 | * a field definition 9 | * 10 | * @tparam Id the id of the field 11 | * @tparam Value the value stored in the field 12 | **/ 13 | template 14 | class field; 15 | 16 | template 17 | class field, Value>{ 18 | public: 19 | using id_type = id; 20 | 21 | field(){} 22 | 23 | field(const Value &val_): m_val{val_}{} 24 | field(Value &&val_): m_val{std::move(val_)}{} 25 | 26 | field &operator =(const Value &rhs){ 27 | m_val = rhs; 28 | return *this; 29 | } 30 | 31 | field &operator =(Value &&rhs){ 32 | m_val = std::move(rhs); 33 | return *this; 34 | } 35 | 36 | /** 37 | * get a constant reference to the value stored 38 | **/ 39 | const Value &get() const noexcept{ return m_val; } 40 | 41 | /** 42 | * get a reference to the value stored 43 | **/ 44 | Value &get() noexcept{ return m_val; } 45 | 46 | private: 47 | Value m_val; 48 | }; 49 | } 50 | 51 | #endif // DBPP_FIELD_HPP 52 | -------------------------------------------------------------------------------- /include/dbpp/id.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DBPP_ID_HPP 2 | #define DBPP_ID_HPP 1 3 | 4 | #include 5 | #include 6 | 7 | #include "typestring.hh" 8 | 9 | namespace dbpp{ 10 | /** 11 | * id used for identifying types 12 | **/ 13 | template 14 | using id = irqus::typestring; 15 | } 16 | 17 | #define dbpp_id(str) typestring_is(str) 18 | 19 | #endif // DBPP_ID_HPP 20 | -------------------------------------------------------------------------------- /include/dbpp/meta/type_list.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DBPP_META_TYPE_LIST_HPP 2 | #define DBPP_META_TYPE_LIST_HPP 1 3 | 4 | #include 5 | 6 | namespace dbpp{ 7 | namespace meta{ 8 | /** 9 | * a basic list of types 10 | **/ 11 | template 12 | struct type_list; 13 | 14 | /** 15 | * type to hold a numeric index into something 16 | **/ 17 | template 18 | struct idx; 19 | 20 | /** 21 | * meta-function to get a type, based on index, from a type_list 22 | * 23 | * @tparam Idx the index of the type to get 24 | * @tparam TypeList the list of types to get the type from 25 | **/ 26 | template 27 | struct get_type_by_index; 28 | 29 | template 30 | struct get_type_by_index, type_list>{ 31 | using type = typename get_type_by_index, type_list>::type; 32 | }; 33 | 34 | template 35 | struct get_type_by_index, type_list>{ 36 | using type = Head; 37 | }; 38 | 39 | /** 40 | * generic meta-function to get a type from a list based on another meta-function 41 | * 42 | * @tparam Idx the index used 43 | * @tparam TypeList the list of types to index 44 | * @tparam GetTypeFn the meta function to use to get the type 45 | **/ 46 | template class GetTypeFn> 47 | struct get_type{ 48 | using type = typename GetTypeFn::type; 49 | }; 50 | 51 | template class GetTypeFn> 52 | using get_type_t = typename get_type::type; 53 | 54 | template 55 | using get_type_by_index_t = typename get_type_by_index, TypeList>::type; 56 | } 57 | } 58 | 59 | #endif // DBPP_META_TYPE_LIST_HPP 60 | -------------------------------------------------------------------------------- /include/dbpp/meta/utility.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DBPP_META_UTILITY_HPP 2 | #define DBPP_META_UTILITY_HPP 1 3 | 4 | #include "type_list.hpp" 5 | 6 | #include "../id.hpp" 7 | 8 | namespace dbpp{ 9 | namespace meta{ 10 | /** 11 | * meta-function to get a type, based on id, from a type_list 12 | * 13 | * @tparam Id the id of the type to get 14 | * @tparam TypeList the list of id-ed types 15 | **/ 16 | template 17 | struct get_type_by_id; 18 | 19 | template class HeadType, typename HeadId, typename ... HeadOther, typename ... Tail> 20 | struct get_type_by_id, type_list, Tail...>>{ 21 | using type = typename get_type_by_id, type_list>::type; 22 | }; 23 | 24 | template class HeadType, typename ... HeadOther, typename ... Tail> 25 | struct get_type_by_id, type_list, HeadOther...>, Tail...>>{ 26 | using type = HeadType, HeadOther...>; 27 | }; 28 | 29 | /** 30 | * helper meta-function to apply get_type_by_id to a list of types 31 | **/ 32 | template 33 | using get_type_by_id_t = typename get_type_by_id::type; 34 | } 35 | } 36 | 37 | #endif // DBPP_META_UTILITY_HPP 38 | -------------------------------------------------------------------------------- /include/dbpp/record.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DBPP_RECORD_HPP 2 | #define DBPP_RECORD_HPP 1 3 | 4 | #include 5 | 6 | #include "field.hpp" 7 | #include "meta/utility.hpp" 8 | 9 | namespace dbpp{ 10 | /** 11 | * a type of record 12 | * 13 | * @tparam Id the id of the record type 14 | * @tparam IdType the type of id to use for values of this record 15 | * @tparam Fields the fields contained in the record 16 | **/ 17 | template 18 | class record{ 19 | public: 20 | using id_type = IdType; 21 | 22 | record(){} 23 | 24 | template 25 | record(std::tuple args) 26 | : record(std::make_index_sequence{}, args){} 27 | 28 | /** 29 | * get a field from the record instance, by id 30 | * 31 | * @tparam FieldId the id of the field 32 | **/ 33 | template 34 | decltype(auto) get(){ 35 | return std::get< 36 | meta::get_type_by_id_t< 37 | FieldId, meta::type_list 38 | > 39 | >(m_fields); 40 | } 41 | 42 | private: 43 | template 44 | record(std::index_sequence, std::tuple &args){ 45 | using dummy = int[]; 46 | (void)dummy{0, (std::get(m_fields) = std::get(args), 0)...}; 47 | } 48 | 49 | std::tuple m_fields; 50 | }; 51 | } 52 | 53 | #endif // DBPP_RECORD_HPP 54 | -------------------------------------------------------------------------------- /include/dbpp/typestring.hh: -------------------------------------------------------------------------------- 1 | /*~ 2 | * Copyright (C) 2015, 2016 George Makrydakis 3 | * 4 | * The 'typestring' header is a single header C++ library for creating types 5 | * to use as type parameters in template instantiations, repository available 6 | * at https://github.com/irrequietus/typestring. Conceptually stemming from 7 | * own implementation of the same thing (but in a more complicated manner to 8 | * be revised) in 'clause': https://github.com/irrequietus/clause. 9 | * 10 | * File subject to the terms and conditions of the Mozilla Public License v 2.0. 11 | * If a copy of the MPLv2 license text was not distributed with this file, you 12 | * can obtain it at: http://mozilla.org/MPL/2.0/. 13 | */ 14 | 15 | #ifndef IRQUS_TYPESTRING_HH_ 16 | #define IRQUS_TYPESTRING_HH_ 17 | 18 | namespace irqus { 19 | 20 | /*~ 21 | * @desc A class 'storing' strings into distinct, reusable compile-time types that 22 | * can be used as type parameters in a template parameter list. 23 | * @tprm C... : char non-type parameter pack whose ordered sequence results 24 | * into a specific string. 25 | * @note Could have wrapped up everything in a single class, eventually will, 26 | * once some compilers fix their class scope lookups! I have added some 27 | * utility functions because asides being a fun little project, it is of 28 | * use in certain constructs related to template metaprogramming 29 | * nonetheless. 30 | */ 31 | template 32 | struct typestring final { 33 | private: 34 | static constexpr char const vals[sizeof...(C)+1] = { C...,'\0' }; 35 | static constexpr unsigned int sval = sizeof...(C); 36 | public: 37 | 38 | static constexpr char const * data() noexcept 39 | { return &vals[0]; } 40 | 41 | static constexpr unsigned int size() noexcept 42 | { return sval; }; 43 | 44 | static constexpr char const * cbegin() noexcept 45 | { return &vals[0]; } 46 | 47 | static constexpr char const * cend() noexcept 48 | { return &vals[sval]; } 49 | }; 50 | 51 | template 52 | constexpr char const typestring::vals[sizeof...(C)+1]; 53 | 54 | //*~ part 1: preparing the ground, because function templates are awesome. 55 | 56 | /*~ 57 | * @note While it is easy to resort to constexpr strings for use in constexpr 58 | * metaprogramming, what we want is to convert compile time string in situ 59 | * definitions into reusable, distinct types, for use in advanced template 60 | * metaprogramming techniques. We want such features because this kind of 61 | * metaprogramming constitutes a pure, non-strict, untyped functional 62 | * programming language with pattern matching where declarative semantics 63 | * can really shine. 64 | * 65 | * Currently, there is no feature in C++ that offers the opportunity to 66 | * use strings as type parameter types themselves, despite there are 67 | * several, different library implementations. This implementation is a 68 | * fast, short, single-header, stupid-proof solution that works with any 69 | * C++11 compliant compiler and up, with the resulting type being easily 70 | * reusable throughout the code. 71 | * 72 | * @usge Just include the header and enable -std=c++11 or -std=c++14 etc, use 73 | * like in the following example: 74 | * 75 | * typestring_is("Hello!") 76 | * 77 | * is essentially identical to the following template instantiation: 78 | * 79 | * irqus::typestring<'H', 'e', 'l', 'l', 'o', '!'> 80 | * 81 | * By passing -DUSE_TYPESTRING= during compilation, you can 82 | * set the maximum length of the 'typestring' from 1 to 1024 (2^0 to 2^10). 83 | * Although all preprocessor implementations tested are capable of far 84 | * more with this method, exceeding this limit may cause internal compiler 85 | * errors in most, with at times rather hilarious results. 86 | */ 87 | 88 | template 89 | constexpr char tygrab(char const(&c)[M]) noexcept 90 | { return c[N < M ? N : M-1]; } 91 | 92 | //*~ part2: Function template type signatures for type deduction purposes. In 93 | // other words, exploiting the functorial nature of parameter packs 94 | // while mixing them with an obvious catamorphism through pattern 95 | // matching galore (partial ordering in this case in C++ "parlance"). 96 | 97 | template 98 | auto typoke(typestring) // as is... 99 | -> typestring; 100 | 101 | template 102 | auto typoke(typestring, typestring<'\0'>, typestring...) 103 | -> typestring; 104 | 105 | template 106 | auto typoke(typestring, typestring, typestring...) 107 | -> decltype(typoke(typestring(), typestring()...)); 108 | 109 | template 110 | auto typeek(typestring) 111 | -> decltype(typoke(typestring()...)); 112 | 113 | template 114 | auto tycat_(typestring, typestring, X... x) 115 | -> decltype(tycat_(typestring(), x...)); 116 | 117 | template 118 | auto tycat_(typestring) 119 | -> typestring; 120 | 121 | /* 122 | * Some people actually using this header as is asked me to include 123 | * a typestring "cat" utility given that it is easy enough to implement. 124 | * I have added this functionality through the template alias below. For 125 | * the obvious implementation, nothing more to say. All T... must be 126 | * of course, "typestrings". 127 | */ 128 | template 129 | using tycat 130 | = decltype(tycat_(T()...)); 131 | 132 | } /* irqus */ 133 | 134 | 135 | //*~ part3: some necessary code generation using preprocessor metaprogramming! 136 | // There is functional nature in preprocessor metaprogramming as well. 137 | 138 | /*~ 139 | * @note Code generation block. Undoubtedly, the preprocessor implementations 140 | * of both clang++ and g++ are relatively competent in producing a 141 | * relatively adequate amount of boilerplate for implementing features 142 | * that the language itself will probably be having as features in a few 143 | * years. At times, like herein, the preprocessor is able to generate 144 | * boilerplate *extremely* fast, but over a certain limit the compiler is 145 | * incapable of compiling it. For the record, only certain versions of 146 | * g++ where capable of going beyond 4K, so I thought of going from base 147 | * 16 to base 2 for USE_TYPESTRING power base. For the record, it takes 148 | * a few milliseconds to generate boilerplate for several thousands worth 149 | * of "string" length through such an 'fmap' like procedure. 150 | */ 151 | 152 | /* 2^0 = 1 */ 153 | #define TYPESTRING1(n,x) irqus::tygrab<0x##n##0>(x) 154 | 155 | /* 2^1 = 2 */ 156 | #define TYPESTRING2(n,x) irqus::tygrab<0x##n##0>(x), irqus::tygrab<0x##n##1>(x) 157 | 158 | /* 2^2 = 2 */ 159 | #define TYPESTRING4(n,x) \ 160 | irqus::tygrab<0x##n##0>(x), irqus::tygrab<0x##n##1>(x) \ 161 | , irqus::tygrab<0x##n##2>(x), irqus::tygrab<0x##n##3>(x) 162 | 163 | /* 2^3 = 8 */ 164 | #define TYPESTRING8(n,x) \ 165 | irqus::tygrab<0x##n##0>(x), irqus::tygrab<0x##n##1>(x) \ 166 | , irqus::tygrab<0x##n##2>(x), irqus::tygrab<0x##n##3>(x) \ 167 | , irqus::tygrab<0x##n##4>(x), irqus::tygrab<0x##n##5>(x) \ 168 | , irqus::tygrab<0x##n##6>(x), irqus::tygrab<0x##n##7>(x) 169 | 170 | /* 2^4 = 16 */ 171 | #define TYPESTRING16(n,x) \ 172 | irqus::tygrab<0x##n##0>(x), irqus::tygrab<0x##n##1>(x) \ 173 | , irqus::tygrab<0x##n##2>(x), irqus::tygrab<0x##n##3>(x) \ 174 | , irqus::tygrab<0x##n##4>(x), irqus::tygrab<0x##n##5>(x) \ 175 | , irqus::tygrab<0x##n##6>(x), irqus::tygrab<0x##n##7>(x) \ 176 | , irqus::tygrab<0x##n##8>(x), irqus::tygrab<0x##n##9>(x) \ 177 | , irqus::tygrab<0x##n##A>(x), irqus::tygrab<0x##n##B>(x) \ 178 | , irqus::tygrab<0x##n##C>(x), irqus::tygrab<0x##n##D>(x) \ 179 | , irqus::tygrab<0x##n##E>(x), irqus::tygrab<0x##n##F>(x) 180 | 181 | /* 2^5 = 32 */ 182 | #define TYPESTRING32(n,x) \ 183 | TYPESTRING16(n##0,x),TYPESTRING16(n##1,x) 184 | 185 | /* 2^6 = 64 */ 186 | #define TYPESTRING64(n,x) \ 187 | TYPESTRING16(n##0,x), TYPESTRING16(n##1,x), TYPESTRING16(n##2,x) \ 188 | , TYPESTRING16(n##3,x) 189 | 190 | /* 2^7 = 128 */ 191 | #define TYPESTRING128(n,x) \ 192 | TYPESTRING16(n##0,x), TYPESTRING16(n##1,x), TYPESTRING16(n##2,x) \ 193 | , TYPESTRING16(n##3,x), TYPESTRING16(n##4,x), TYPESTRING16(n##5,x) \ 194 | , TYPESTRING16(n##6,x), TYPESTRING16(n##7,x) 195 | 196 | /* 2^8 = 256 */ 197 | #define TYPESTRING256(n,x) \ 198 | TYPESTRING16(n##0,x), TYPESTRING16(n##1,x), TYPESTRING16(n##2,x) \ 199 | , TYPESTRING16(n##3,x), TYPESTRING16(n##4,x), TYPESTRING16(n##5,x) \ 200 | , TYPESTRING16(n##6,x), TYPESTRING16(n##7,x), TYPESTRING16(n##8,x) \ 201 | , TYPESTRING16(n##9,x), TYPESTRING16(n##A,x), TYPESTRING16(n##B,x) \ 202 | , TYPESTRING16(n##C,x), TYPESTRING16(n##D,x), TYPESTRING16(n##E,x) \ 203 | , TYPESTRING16(n##F,x) 204 | 205 | /* 2^9 = 512 */ 206 | #define TYPESTRING512(n,x) \ 207 | TYPESTRING256(n##0,x), TYPESTRING256(n##1,x) 208 | 209 | /* 2^10 = 1024 */ 210 | #define TYPESTRING1024(n,x) \ 211 | TYPESTRING256(n##0,x), TYPESTRING256(n##1,x), TYPESTRING256(n##2,x) \ 212 | , TYPESTRING128(n##3,x), TYPESTRING16(n##38,x), TYPESTRING16(n##39,x) \ 213 | , TYPESTRING16(n##3A,x), TYPESTRING16(n##3B,x), TYPESTRING16(n##3C,x) \ 214 | , TYPESTRING16(n##3D,x), TYPESTRING16(n##3E,x), TYPESTRING16(n##3F,x) 215 | 216 | //*~ part4 : Let's give some logic with a -DUSE_TYPESTRING flag! 217 | 218 | #ifdef USE_TYPESTRING 219 | #if USE_TYPESTRING == 0 220 | #define typestring_is(x) \ 221 | decltype(irqus::typeek(irqus::typestring())) 222 | #elif USE_TYPESTRING == 1 223 | #define typestring_is(x) \ 224 | decltype(irqus::typeek(irqus::typestring())) 225 | #elif USE_TYPESTRING == 2 226 | #define typestring_is(x) \ 227 | decltype(irqus::typeek(irqus::typestring())) 228 | #elif USE_TYPESTRING == 3 229 | #define typestring_is(x) \ 230 | decltype(irqus::typeek(irqus::typestring())) 231 | #elif USE_TYPESTRING == 4 232 | #define typestring_is(x) \ 233 | decltype(irqus::typeek(irqus::typestring())) 234 | #elif USE_TYPESTRING == 5 235 | #define typestring_is(x) \ 236 | decltype(irqus::typeek(irqus::typestring())) 237 | #elif USE_TYPESTRING == 6 238 | #define typestring_is(x) \ 239 | decltype(irqus::typeek(irqus::typestring())) 240 | #elif USE_TYPESTRING == 7 241 | #define typestring_is(x) \ 242 | decltype(irqus::typeek(irqus::typestring())) 243 | #elif USE_TYPESTRING == 8 244 | #define typestring_is(x) \ 245 | decltype(irqus::typeek(irqus::typestring())) 246 | #elif USE_TYPESTRING == 9 247 | #define typestring_is(x) \ 248 | decltype(irqus::typeek(irqus::typestring())) 249 | #elif USE_TYPESTRING == 10 250 | #define typestring_is(x) \ 251 | decltype(irqus::typeek(irqus::typestring())) 252 | #elif USE_TYPESTRING > 10 253 | 254 | #warning !!!: custom typestring length exceeded allowed (1024) !!! 255 | #warning !!!: all typestrings to default maximum typestring length of 64 !!! 256 | #warning !!!: you can use -DUSE_TYPESTRING= to set length !!! 257 | 258 | #define typestring_is(x) \ 259 | decltype(irqus::typeek(irqus::typestring())) 260 | 261 | #elif USE_TYPESTRING < 0 262 | 263 | #warning !!!: You used USE_TYPESTRING with a negative size specified !!! 264 | #warning !!!: all typestrings to default maximum typestring length of 64 !!! 265 | #warning !!!: you can use -DUSE_TYPESTRING= to set length !!! 266 | 267 | #define typestring_is(x) \ 268 | decltype(irqus::typeek(irqus::typestring())) 269 | 270 | #endif 271 | #else 272 | #define typestring_is(x) \ 273 | decltype(irqus::typeek(irqus::typestring())) 274 | #endif 275 | #endif /* IRQUS_TYPESTRING_HH_ */ 276 | --------------------------------------------------------------------------------