code_junkie

Can this macro be converted to a function?

Nov 11th, 2011
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.25 KB | None | 0 0
  1. #define STRUCTSIZE(s) (sizeof(s) / sizeof(*s))
  2.  
  3. template<typename T,int SIZE>
  4. inline size_t array_size(const T (&array)[SIZE])
  5. {
  6. return SIZE;
  7. }
  8.  
  9. constexpr size_t array_size(const T (&array)[SIZE])
  10.  
  11. #include <boost/typeof/typeof.hpp>
  12.  
  13. template<typename T>
  14. struct ArraySize
  15. {
  16. private: static T x;
  17. public: enum { size = sizeof(T)/sizeof(*x)};
  18. };
  19. template<typename T>
  20. struct ArraySize<T*> {};
  21.  
  22. ArraySize<BOOST_TYPEOF(foo)>::size
  23.  
  24. // asize.hpp
  25. template < typename T >
  26. struct asize; // no implementation for all types...
  27.  
  28. template < typename T, size_t N >
  29. struct asize< T[N] > { // ...except arrays
  30. static const size_t val = N;
  31. };
  32.  
  33. template< size_t N >
  34. struct count_type { char val[N]; };
  35.  
  36. template< typename T, size_t N >
  37. count_type< N > count( const T (&)[N] ) {}
  38.  
  39. #define ASIZE( a ) ( sizeof( count( a ).val ) )
  40. #define ASIZET( A ) ( asize< A >::val )
  41.  
  42. // asize_test.cpp
  43. #include <boost/static_assert.hpp>
  44. #include "asize.hpp"
  45.  
  46. #define OLD_ASIZE( a ) ( sizeof( a ) / sizeof( *a ) )
  47.  
  48. typedef char C;
  49. typedef struct { int i; double d; } S;
  50. typedef C A[42];
  51. typedef S B[42];
  52. typedef C * PA;
  53. typedef S * PB;
  54.  
  55. int main() {
  56. A a; B b; PA pa; PB pb;
  57. BOOST_STATIC_ASSERT( ASIZET( A ) == 42 );
  58. BOOST_STATIC_ASSERT( ASIZET( B ) == 42 );
  59. BOOST_STATIC_ASSERT( ASIZET( A ) == OLD_ASIZE( a ) );
  60. BOOST_STATIC_ASSERT( ASIZET( B ) == OLD_ASIZE( b ) );
  61. BOOST_STATIC_ASSERT( ASIZE( a ) == OLD_ASIZE( a ) );
  62. BOOST_STATIC_ASSERT( ASIZE( b ) == OLD_ASIZE( b ) );
  63. BOOST_STATIC_ASSERT( OLD_ASIZE( pa ) != 42 ); // logic error: pointer accepted
  64. BOOST_STATIC_ASSERT( OLD_ASIZE( pb ) != 42 ); // logic error: pointer accepted
  65. // BOOST_STATIC_ASSERT( ASIZE( pa ) != 42 ); // compile error: pointer rejected
  66. // BOOST_STATIC_ASSERT( ASIZE( pb ) != 42 ); // compile error: pointer rejected
  67. return 0;
  68. }
  69.  
  70. template<int n>
  71. struct char_array_wrapper{
  72. char result[n];
  73. };
  74.  
  75. template<typename T, int s>
  76. char_array_wrapper<s> the_type_of_the_variable_is_not_an_array(const T (&array)[s]){
  77. }
  78.  
  79.  
  80. #define ARRAYSIZE_OF_VAR(v) sizeof(the_type_of_the_variable_is_not_an_array(v).result)
  81.  
  82. #include <iostream>
  83. using namespace std;
  84.  
  85. int main(){
  86. int foo[42];
  87. int*bar;
  88. cout<<ARRAYSIZE_OF_VAR(foo)<<endl;
  89. // cout<<ARRAYSIZE_OF_VAR(bar)<<endl; fails
  90. }
  91.  
  92. template< typename T > size_t structsize( const T& t ) {
  93. return sizeof( t ) / sizeof( *t );
  94. }
  95.  
  96.  
  97. int ints[] = { 1,2,3 };
  98. assert( structsize( ints ) == 3 );
  99.  
  100. //
  101. // Return the number of elements in a statically sized array.
  102. // DWORD Buffer[100];
  103. // RTL_NUMBER_OF(Buffer) == 100
  104. // This is also popularly known as: NUMBER_OF, ARRSIZE, _countof, NELEM, etc.
  105. //
  106. #define RTL_NUMBER_OF_V1(A) (sizeof(A)/sizeof((A)[0]))
  107.  
  108. #if defined(__cplusplus) &&
  109. !defined(MIDL_PASS) &&
  110. !defined(RC_INVOKED) &&
  111. !defined(_PREFAST_) &&
  112. (_MSC_FULL_VER >= 13009466) &&
  113. !defined(SORTPP_PASS)
  114. //
  115. // RtlpNumberOf is a function that takes a reference to an array of N Ts.
  116. //
  117. // typedef T array_of_T[N];
  118. // typedef array_of_T &reference_to_array_of_T;
  119. //
  120. // RtlpNumberOf returns a pointer to an array of N chars.
  121. // We could return a reference instead of a pointer but older compilers do not accept that.
  122. //
  123. // typedef char array_of_char[N];
  124. // typedef array_of_char *pointer_to_array_of_char;
  125. //
  126. // sizeof(array_of_char) == N
  127. // sizeof(*pointer_to_array_of_char) == N
  128. //
  129. // pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T);
  130. //
  131. // We never even call RtlpNumberOf, we just take the size of dereferencing its return type.
  132. // We do not even implement RtlpNumberOf, we just decare it.
  133. //
  134. // Attempts to pass pointers instead of arrays to this macro result in compile time errors.
  135. // That is the point.
  136. //
  137. extern "C++" // templates cannot be declared to have 'C' linkage
  138. template <typename T, size_t N>
  139. char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];
  140.  
  141. #define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
  142.  
  143. //
  144. // This does not work with:
  145. //
  146. // void Foo()
  147. // {
  148. // struct { int x; } y[2];
  149. // RTL_NUMBER_OF_V2(y); // illegal use of anonymous local type in template instantiation
  150. // }
  151. //
  152. // You must instead do:
  153. //
  154. // struct Foo1 { int x; };
  155. //
  156. // void Foo()
  157. // {
  158. // Foo1 y[2];
  159. // RTL_NUMBER_OF_V2(y); // ok
  160. // }
  161. //
  162. // OR
  163. //
  164. // void Foo()
  165. // {
  166. // struct { int x; } y[2];
  167. // RTL_NUMBER_OF_V1(y); // ok
  168. // }
  169. //
  170. // OR
  171. //
  172. // void Foo()
  173. // {
  174. // struct { int x; } y[2];
  175. // _ARRAYSIZE(y); // ok
  176. // }
  177. //
  178.  
  179. #else
  180. #define RTL_NUMBER_OF_V2(A) RTL_NUMBER_OF_V1(A)
  181. #endif
  182.  
  183. #ifdef ENABLE_RTL_NUMBER_OF_V2
  184. #define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V2(A)
  185. #else
  186. #define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V1(A)
  187. #endif
  188.  
  189. //
  190. // ARRAYSIZE is more readable version of RTL_NUMBER_OF_V2, and uses
  191. // it regardless of ENABLE_RTL_NUMBER_OF_V2
  192. //
  193. // _ARRAYSIZE is a version useful for anonymous types
  194. //
  195. #define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A)
  196. #define _ARRAYSIZE(A) RTL_NUMBER_OF_V1(A)
  197.  
  198. template<typename T, int SIZE>
  199. int arraySize(const T(&arr)[SIZE])
  200. {
  201. return SIZE;
  202. }
  203.  
  204. template <typename T>
  205. uint32_t StructSize() // This might get inlined to a constant at compile time
  206. {
  207. return sizeof(T)/sizeof(*T);
  208. }
  209.  
  210. // or to get it at compile time for shure
  211.  
  212. class StructSize<typename T>
  213. {
  214. enum { result = sizeof(T)/sizeof(*T) };
  215. }
  216.  
  217. #include <iterator>
  218. #include <algorithm>
  219. #include <iostream>
  220.  
  221.  
  222. template<typename T>
  223. struct StructSize
  224. {
  225. private: static T x;
  226. public: enum { size = sizeof(T)/sizeof(*x)};
  227. };
  228.  
  229. template<typename T>
  230. struct StructSize<T*>
  231. {
  232. /* Can only guarantee 1 item (maybe we should even disallow this situation) */
  233. //public: enum { size = 1};
  234. };
  235.  
  236. struct X
  237. {
  238. int operator *();
  239. };
  240.  
  241.  
  242. int main(int argc,char* argv[])
  243. {
  244. int data[] = {1,2,3,4,5,6,7,8};
  245. int copy[ StructSize<typeof(data)>::size];
  246.  
  247. std::copy(&data[0],&data[StructSize<typeof(data)>::size],&copy[0]);
  248. std::copy(&copy[0],&copy[StructSize<typeof(copy)>::size],std::ostream_iterator<int>(std::cout,","));
  249.  
  250. /*
  251. * For extra points we should make the following cause the compiler to generate an error message */
  252. X bad1;
  253. X bad2[StructSize<typeof(bad1)>::size];
  254. }
  255.  
  256. template <typename T>
  257. size_t getTypeSize()
  258. {
  259. return sizeof(T)/sizeof(*T);
  260. }
  261.  
  262. struct JibbaJabba
  263. {
  264. int int1;
  265. float f;
  266. };
  267.  
  268. int main()
  269. {
  270. cout << "sizeof JibbaJabba is " << getTypeSize<JibbaJabba>() << std::endl;
  271. return 0;
  272. }
Add Comment
Please, Sign In to add comment