Generating unique identifiers at compile-time

Meta-Programming, as used in Boost.MPL and others, allows to compute arbitrary values at compile-time, in a Turing-complete manner. However, something like generating unique identifiers at compile-time, which would be fairly useful, requires some kind of entropy source to create a random seed. One can maybe extract some entropy from macros such as __DATE__ and __TIME__, using both preprocessing and templates. Among you boosters, which are well known for your interesting in meta-programming, is there someone who ever tried to look into this?

One can maybe extract some entropy from macros such as __DATE__ and __TIME__, using both preprocessing and templates.
These just expand to a string not a number on which one could do some processing. The only macro that is usable is __LINE__ and when compiling constant expressions sizeof can be used, but these provide only a very low entropy. In other words I haven't found a way to do this either although it would be really easy to add a built in uuid macro to the preprocessor but no one seems to have done that.

On Dec 2, 2007 7:09 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Indeed, but isn't it possible to extract the numerical parts with macros and then inject them in templates?
No, the preprocessor cannot decompose tokens, it can only concatenate them, i.e. it cannot look inside a string.

Here's a dumb idea, but perhaps somebody here (smarter than me) can turn it into one that is actually a useful idea. MSVC compilers have an extra predefined macro named __COUNTER__. This is Microsoft-specific macro that might perhaps be what you're looking for to help you create those unique identifiers. The MSDN description of the macro is as follows: QUOTE Expands to an integer starting with 0 and incrementing by 1 every time it is used in a compiland. __COUNTER__ remembers its state when using precompiled headers. If the last __COUNTER__ value was 4 after building a precompiled header (PCH), it will start with 5 on each PCH use. END_QUOTE Other compilers don't have this built-in macro, but it seems to me that you can create something useful with compiler arguments. For example: g++ main.cpp -D_FILE_ORDINAL_=10000 You also need these macros somewhere that use the ordinal value as follows: #define _COUNTER3( O, L ) O##L #define _COUNTER2( O, L ) _COUNTER3( O, L ) #define _COUNTER _COUNTER2( _FILE_ORDINAL_, __LINE__ ) If every compiled file gets its own large ordinal number, you should never have the same value for _COUNTER twice. Of course the implication is that it's not handled purely by the C++ language. But who knows, if one needs to use boost code that relies on this sort of contraption, maybe they'd be willing to modify their Makefiles. The macros could also be injected directly into the source code itself like this: #define _FILE_ORDINAL_ 10000 #include <boost/some-boost-file.h> int main() { printf( "Value = %d \n", _COUNTER ); printf( "Value2 = %d \n", _COUNTER ); } -Sid Sacek -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Mathias Gaunard Sent: Sunday, December 02, 2007 1:04 PM To: boost@lists.boost.org Subject: [boost] Generating unique identifiers at compile-time Meta-Programming, as used in Boost.MPL and others, allows to compute arbitrary values at compile-time, in a Turing-complete manner. However, something like generating unique identifiers at compile-time, which would be fairly useful, requires some kind of entropy source to create a random seed. One can maybe extract some entropy from macros such as __DATE__ and __TIME__, using both preprocessing and templates. Among you boosters, which are well known for your interesting in meta-programming, is there someone who ever tried to look into this? _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Dec 4, 2007 6:54 AM, Sid Sacek <ssacek@appsecinc.com> wrote:
Other compilers don't have this built-in macro, but it seems to me that you can create something useful with compiler arguments. For example:
g++ main.cpp -D_FILE_ORDINAL_=10000
You also need these macros somewhere that use the ordinal value as follows:
#define _COUNTER3( O, L ) O##L #define _COUNTER2( O, L ) _COUNTER3( O, L ) #define _COUNTER _COUNTER2( _FILE_ORDINAL_, __LINE__ )
If every compiled file gets its own large ordinal number, you should never have the same value for _COUNTER twice.
__LINE__ is not unique in a translation unit. For each included header, it is restarted from 1. So if you happen to use _COUNTER in two boost header files at the same line, and the two headers are included by the same c++ file, you end up with clashing counters. Corrado

__LINE__ is not unique in a translation unit. For each included header, it is restarted from 1. So if you happen to use _COUNTER in two boost header files at the same line, and the two headers are included by the same c++ file, you end up with clashing counters. Corrado
You totally missed the point! Macros like _COUNTER are not meant to be expanded inside of header files. They're designed to expand inside cpp source files, or be used as part of other macros. We all know what the limitations of __LINE__ are, we learned that stuff 20 years ago!

__LINE__ is not unique in a translation unit. For each included header, it is restarted from 1. So if you happen to use _COUNTER in two boost header files at the same line, and the two headers are included by the same c++ file, you end up with clashing counters. Corrado
You totally missed the point!
Macros like _COUNTER are not meant to be expanded inside of header files. They're designed to expand inside cpp source files, or be used as part of other macros.
We all know what the limitations of __LINE__ are, we learned that stuff 20 years ago!
What about using BOOST_PP_COUNTER()/BOOST_PP_UPDATE_COUNTER() ? Regards Hartmut

Mathias Gaunard wrote:
One can maybe extract some entropy from macros such as __DATE__ and __TIME__, using both preprocessing and templates.
I had another crazy idea: exploit the fact that date and time are separate to map the rather limited (compared to full time) range of possibilities. template<const char*> struct date { }; template<> struct<"Dec 4 2007"> { static const int month = 12; static const int day = 4; static const int year = 2007; }; then use struct<__DATE__>. However it seems C++ doesn't allow this either?

On 12/4/07, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
I had another crazy idea: exploit the fact that date and time are separate to map the rather limited (compared to full time) range of possibilities.
then use struct<__DATE__>.
However it seems C++ doesn't allow this either?
That's because you cannot instantiate a class template with a string in C++.

That's because you cannot instantiate a class template with a string in C++.
Actually you can, but are limited to strings with external linkage. Another problem with this aspect of templates is that not all compilers support this syntax yet. -Sid Sacek #include <stdio.h> template< const char * name > class foo { const char * val; public: foo() : val( name ) { } const char * value( void ) { return val; } }; extern const char exname[] = "hello world"; int main( int, char ** ) { foo< exname > myfoo; printf( " %s \n", myfoo.value() ); }

On Dec 2, 2007 11:04 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Meta-Programming, as used in Boost.MPL and others, allows to compute arbitrary values at compile-time, in a Turing-complete manner.
However, something like generating unique identifiers at compile-time, which would be fairly useful, requires some kind of entropy source to create a random seed.
One can maybe extract some entropy from macros such as __DATE__ and __TIME__, using both preprocessing and templates.
Among you boosters, which are well known for your interesting in meta-programming, is there someone who ever tried to look into this?
OK, this is funny - on GCC 4.0.1/darwin, I was able to: #include __DATE__ which means you can have a date-based seed given a huge number of files to include. I don't know if this works with all compilers though. Too bad #include __TIME__ doesn't work, because of ":"s in the literal... but maybe someone can take this further and figure something out. Stjepan
participants (6)
-
Corrado Zoccolo
-
Hartmut Kaiser
-
Kevin Sopp
-
Mathias Gaunard
-
Sid Sacek
-
Stjepan Rajko