Novelty: autmatically assigning unique integral type ids

Hi all, Attached is some non-conforming code which automatically assigns a unique integer id to an arbitrary type. It's based on this post by Daniel Wallin: http://lists.boost.org/MailArchives/boost/msg69842.php Example: #include <boost/static_assert.hpp> #include <boost/unique_id.hpp> int main() { BOOST_STATIC_ASSERT(BOOST_UNIQUE_ID(void) == 0); BOOST_STATIC_ASSERT(BOOST_UNIQUE_ID(bool) == 1); BOOST_STATIC_ASSERT(BOOST_UNIQUE_ID(char) == 2); BOOST_STATIC_ASSERT(BOOST_UNIQUE_ID(void) == 0); BOOST_STATIC_ASSERT(BOOST_UNIQUE_ID(bool) == 1); BOOST_STATIC_ASSERT(BOOST_UNIQUE_ID(char) == 2); } Obviously the ids assigned will be different depending on the order in which types are passed to BOOST_UNIQUE_ID. It's a novelty not just because it's non-conforming but also because after assigning ids to about fifty types it slows down to a deadly crawl, and maxes out at about 110 types (on VC7.1, using over 300MB RAM). I tried several forms of loop unrolling, and they don't help much. I'm posting this now because yesterday I figured out how to make it work on EDG (except for Comeau). It now works on VC7.1, VC8.0 (beta), GCC 3.2 (MinGW), GCC 3.4.1 (Cygwin), Intel 7.0 and 8.0 for Windows (in strict mode), and on the preview of the Borland EDG-based compiler I downloaded about half a year ago. I still need conforming-compiler workarounds for Comeau and Metrowerks. ;-) Best Regards, Jonathan begin 666 unique_id.zip M4$L#! H``````'%R@S$````````````````/````;&EB<R]U;FEQ=65?:60O M4$L#!!0````(`!AP@S&5>-46[ ```+(&```7````;&EB<R]U;FEQ=65?:60O M=&5S="YC<'#MTT]/PC 8!O![DWZ')ERV"SB4?T%,4#GL`M&-<U/6RIJ4%M?6 MB_&[.SM%PHEW5^AQW2_/F_1Y.U(7RG-![C?&6->SCCE94&:MJ%RWW.\?,.J< M_..U?/>"2OY[CY'4CNR8U%&,T2=&I#Z/JU66TRR?Y^D3G6?9XC6/FF_K9?JR M7M#T.?HPDL=D-B,W\?1\50^A@DH@JBA9%50?HJS<:L')`=]"L->G_ Z479K* M!39HE?KOAQ!?OV5 HU:A?WH,T<KH;5"35ID'GH!Z]*8,:X9-0$WBQF^4:""H M3#]SDF,-:M-U6:[+<O'+\H71-U!+`P0*``````"<<H,Q```````````````` M!0```&QI8G,O4$L#!!0````(`$-O@S'*X)&D;@,``*,+```3````8F]O<W0O M=6YI<75E7VED+FAP<*5638^;,!"]K[3_8:1>8)M"4O7D4J0V&ZFI*K95V%XM M+PR)56*H,=VF5?][;2"$+!\;J3XA_&;FS;-G/*X+UM*&998?)-_N%'S*!%,[ M)B LY7<F> &OY_,WSO65Z\(M+Y3D#Z7"&$H1HP2U0_B0986"39:H1R81/O,( M18$S^(:RX)F A3-WP-H@`HNB;)\S<>!B6SE,>*H-ULM5L%G1!9T[ZI>"3$*D MZ0!3L%,J)Z[[^/CH/)@H3B:W[A.\8U]?'=E%*>-[E 2"3 %KF*7\03)Y< SL M!4\T[P0^W-UM0GH?K+_>K^CZEG[\\H6N@^7G^]O5K49I"!?X#,IX$U%:Q@A> MQ<Z-,I'PK;/+<[^_N<]3%W^RE/)D`L%C%(JKPQ1$J(G=G'$YLJT..5(E&5>% M&Z-B/'4/6%"14;-S@1$OZ,^,QR/(4O%4,W=1L(<43VF.ZFF%-A!2&1-2"OZC MU%:Q!R'XA)BXA&B]2C0N!-MCD;,(H<+#G_.?=3KF+_37]95"+0U3Z!FOQ@I" MMM74.LD1TN@`+1.ZPS1':6GL#!S'L=^:H .^M"==&&6D.K9<HXY\!L//0!\D M!'X-:>WW3'[7Y=7)I%9M$[X/UTNZO OT5Q!:1H=T!I5 \.X\[X+_QBRQAA*Q M[!E8F@TA.CKU`O_&GMMV7[9WPRZ'!+/!"',$FC^FPJH8AB/U*HY^M=,`_U9* M5O">-/<S:+^?J"/PEZ)#$AV#'@W[^51TFO+S!F])J[UWDF?NSR!H;J$_&S:K MT4W9CKAN<:8Z)S MKCZ<)C+<P.NQZ'VKN3^.'-F:3&U:-+,&A%M<()Q9EXK7 M8B\0L,7V1(27L'A.R'/KQ8289DUI?7':IJ>.G4S_=],;06)1IFJ@\OZK")H6 M[]7>QW(X*T3/E.R X$;LZ:O5*M!$&T]VN'<\2?@IK;!+:^ZWSLZEZWFI=PE) MN-0/S?CJ<!KU4:">">()'VS[]MCBF.*1GGR$#FI>AJ:S0^<AG.B:]7M6.ZIZ M98QZ&))($\E1##9+$Z23@UD-^*S+FQ&ADNT$&WXA3UI;-?=7AE5#W79U#[NQ MGS_#<]Z>%J@]MK/%M4Y,WQZF,JF]U1[_@IX#5SH#XRHO3I.!<_G+7?,BG71J M%YT1I7K<O= _-KC:Y \,D*C&DZ(>6NH)5&?%$P.Y;!:]OOH'4$L#! H````` M`)ER@S$````````````````&````8F]O<W0O4$L!`A0`"@``````<7*#,0`` M``````````````\````````````0`````````&QI8G,O=6YI<75E7VED+U!+ M`0(4`!0````(`!AP@S&5>-46[ ```+(&```7``````````$`( ```"T```!L M:6)S+W5N:7%U95]I9"]T97-T+F-P<%!+`0(4``H``````)QR@S$````````` M```````%````````````$ ```$X!``!L:6)S+U!+`0(4`!0````(`$-O@S'* MX)&D;@,``*,+```3``````````$`( ```'$!``!B;V]S="]U;FEQ=65?:60N M:'!P4$L!`A0`"@``````F7*#,0````````````````8````````````0```` @$ 4``&)O;W-T+U!+!08`````!0`%`"H!```T!0`````` ` end

"Arkadiy Vertleyb" <vertleyb@hotmail.com> wrote
"Jonathan Turkanis" <technews@kangaroologic.com> wrote
Attached is some non-conforming code which automatically assigns a unique integer id to an arbitrary type.
Could you put this into the files section -- I can't access the attachement...
Please disregard -- I got it... Arkadiy

Jonathan Turkanis wrote:
I'm posting this now because yesterday I figured out how to make it work on EDG (except for Comeau).
Unfortunately, it doesn't work on Intel Linux in strict mode, it just gives 0 every time. If I understand the problem correctly (and I'm not sure that I do), the declaration of unique_id_helper that you want to find is inside unique_id_impl<T>::declare_friend<Tag> which is neither in scope, or subject to ADL, when it is 'called' in unique_id_impl<T>::unmarked<Tag, N>. So only the 'no_type' declaration in boost::detail is found. I hope that makes sense. Daniel

Sorry, I just reread my mail and there was a mistake: Daniel James wrote:
If I understand the problem correctly (and I'm not sure that I do), the declaration of unique_id_helper that you want to find is inside unique_id_impl<T>::declare_friend<Tag> which is neither in scope, or
That should be 'inside unique_id_impl<T>::declare_friend<Tag>'s namespace which is ....'
subject to ADL, when it is 'called' in unique_id_impl<T>::unmarked<Tag, N>. So only the 'no_type' declaration in boost::detail is found.
Just to be clear, unique_id_impl<T>::declare_friend<Tag> is in scope but its namespace is not. Daniel

"Daniel James" <daniel@calamity.org.uk> wrote in message news:cos20v$vrh$1@sea.gmane.org...
Jonathan Turkanis wrote:
I'm posting this now because yesterday I figured out how to make it work on EDG (except for Comeau).
Unfortunately, it doesn't work on Intel Linux in strict mode, it just gives 0 every time.
Too bad :( That's what happens on Comeau and Metrowerks. Intel is such a strange beast -- I'm using the strict ANSI option (/Za) and the option to disable Microsoft bug emulation (/Qms0). Jonathan

Jonathan Turkanis wrote:
Too bad :( That's what happens on Comeau and Metrowerks. Intel is such a strange beast -- I'm using the strict ANSI option (/Za) and the option to disable Microsoft bug emulation (/Qms0).
Here's an alternative based on a mix of Daniel Wallin and Goran Mitrovic's code. I believe it is standards compliant. And, in theory, can allocate up to 4096 ids. It should be easy to extend it do more, although compile times will probably put you of doing that. The problem is, that to use it you have to set the type index at the global scope and it can't be called from a template. Because of that, it doesn't offer much advantge over using the preprocessor to allocate ids and would probably result in larger compile times. Daniel

"Daniel James" <daniel@calamity.org.uk> wrote in message news:coss3j$k2u$1@sea.gmane.org...
Jonathan Turkanis wrote:
Too bad :( That's what happens on Comeau and Metrowerks. Intel is such a strange beast -- I'm using the strict ANSI option (/Za) and the option to disable Microsoft bug emulation (/Qms0).
Here's an alternative based on a mix of Daniel Wallin and Goran Mitrovic's code.
Congrulations on figuring out Goran's code. It was written in such peculiar notation and coding-style that I gave up after a few lines.
I believe it is standards compliant.
I haven't looked at it yet, but I don't see how code which could assign different id's to the same type in different translation units could be compliant. I guess you have to take special care to ensure unique id's?
And, in theory, can allocate up to 4096 ids. It should be easy to extend it do more, although compile times will probably put you of doing that.
The problem is, that to use it you have to set the type index at the global scope and it can't be called from a template.
Yes, this seemed like a serious limitation of Goran's method based on his examples. I'd like the id to be set implicitly the first time it's queried.
Because of that, it doesn't offer much advantge over using the preprocessor to allocate ids and would probably result in larger compile times.
:(
Daniel
Best Regards, Jonathan

On 12/3/04 4:59 PM, "Jonathan Turkanis" <technews@kangaroologic.com> wrote:
Attached is some non-conforming code which automatically assigns a unique integer id to an arbitrary type. It's based on this post by Daniel Wallin:
http://lists.boost.org/MailArchives/boost/msg69842.php [TRUNCATE]
I take that computing these IDs at compile-time is a requirement? Otherwise you could use something like: reinterpret_cast<unsigned>(static_cast<void const *>(&typeid(T))); This assumes that a void-pointer can fit within an unsigned. If not, use the appropriate type that corresponds to C-1999's "uintptr_t". (Of course it's possible that there's _no_ integral type big enough to fit a pointer. In that case, my plan is screwed.) -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com

"Daryle Walker" <darylew@hotmail.com> wrote in message news:BAY23-DAV2FA8157E525BDF2DA9F2BBFB30@phx.gbl...
On 12/3/04 4:59 PM, "Jonathan Turkanis" <technews@kangaroologic.com> wrote:
Attached is some non-conforming code which automatically assigns a unique integer id to an arbitrary type. It's based on this post by Daniel Wallin:
http://lists.boost.org/MailArchives/boost/msg69842.php [TRUNCATE]
I take that computing these IDs at compile-time is a requirement?
That's the idea. Fortunately it's not a requirement of anything, since it's not really possible ;-)
Otherwise you could use something like:
reinterpret_cast<unsigned>(static_cast<void const *>(&typeid(T)));
This assumes that a void-pointer can fit within an unsigned.
You don't need typeid -- you can just do: template<typename T> struct unique_id_holder { static char val; }; template<typename T> char unique_id_holder::val; template<typename T> int unique_id() { return reinterpret_cast<int>(&unique_id_holder::val); } Jonathan

On Sat, 4 Dec 2004 23:44:46 -0700 "Jonathan Turkanis" <technews@kangaroologic.com> wrote:
You don't need typeid -- you can just do:
template<typename T> struct unique_id_holder { static char val; };
template<typename T> char unique_id_holder::val;
template<typename T> int unique_id() { return reinterpret_cast<int>(&unique_id_holder::val); }
For "better" portability, you should make that "int" a "long." Also, note that the following assertions will be true... struct Foo { }; assert(typeid(Foo) == typeid(Foo)); assert(typeid(Foo) == typeid(Foo &)); assert(typeid(Foo) == typeid(Foo const)); assert(typeid(Foo) == typeid(Foo const &)); long tid[4]; tid[0] = unique_id<Foo>(); tid[1] = unique_id<Foo &>(); tid[2] = unique_id<Foo const>(); tid[3] = unique_id<Foo const &>(); for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { if (i == j) { assert(tid[i] == tid[j]); } else { assert(tid[i] != tid[j]); } } } which is probably obvious to some, but not all, and the implications are possibly a bit more subtle. Specifically, each of the above will get a different ID when calling unique_id<T>() with modifiers and references, but they will get the "same" std::type_info for those calls.

"Jody Hagins" <jody-boost-011304@atdesk.com> wrote in message news:20041206153207.0dd11478.jody-boost-011304@atdesk.com...
On Sat, 4 Dec 2004 23:44:46 -0700 "Jonathan Turkanis" <technews@kangaroologic.com> wrote:
You don't need typeid -- you can just do:
template<typename T> struct unique_id_holder { static char val; };
template<typename T> char unique_id_holder::val;
template<typename T> int unique_id() { return reinterpret_cast<int>(&unique_id_holder::val); }
For "better" portability, you should make that "int" a "long."
True. Daryle mentioned the problems about the size of integral types, and I was taking it for granted. The reason it doesn't matter much is that the applications which could benifit from a compile-time type id could do just as well if the id were split into several components.
Specifically, each of the above will get a different ID when calling unique_id<T>() with modifiers and references, but they will get the "same" std::type_info for those calls.
Yes, good point. It would be nice, for several purposes, if typeid were less forgetful. Jonathan
participants (5)
-
Arkadiy Vertleyb
-
Daniel James
-
Daryle Walker
-
Jody Hagins
-
Jonathan Turkanis