Project-wide unique identifiers at compiletime

Started by
9 comments, last by CJM 18 years, 9 months ago
Hey, I'm currently working on a project which requires that at compiletime unique identifiers [ints in particular] can be created. Currently, this forces the users of my project to need to manually use different numbers, but this is not a valid solution. My question is: Is it possible to generate unique numbers which have a project-scope [ie the Visual Studio __COUNT__ macro would be acceptable, but it appears to work only in a single file's scope (perhaps someone knows how to tweak this so that it generates a global count)]. If worst comes to worst, I'm thinking I could make a custom build step which goes through and replaces my own macro (ie __GLOBALCOUNT__, or something less standards-breaking) with everincreasing numbers and then compiles that instead or something - but it's an awful lot of effort for something [which probably wouldn't work] which I would have thought was easier than it's turning out to be. --CJM
Advertisement
//UniqueIDGen.h#ifndef _UNIQUE_ID_GEN_#define _UNIQUE_ID_GEN_class CUniqueIDGen{		//Integer used to generate unique ids		static unsigned int m_iIds;	public:		//constructor and destructor, do nothing		CUniqueIDGen(void) {}		virtual ~CUniqueIDGen(void) {}		/*********************************************		* Function:	GetID		*		* Return:		*	int: a unique id		*		* Purpose:	Function to generate unique class ids		*		*********************************************/		static unsigned int GetID();};#endif

//uniqueidgen.cpp#include "UniqueIDGen.h"unsigned int CUniqueIDGen::m_iIds = 0;/********************************************** Function:	GetID** Return:*	unsigned int: a unique id** Purpose:	Function to generate unique class ids**********************************************/unsigned int CUniqueIDGen::GetID(){	return CUniqueIDGen::m_iIds++;}

Call CUniqueIDGen::GetID() when you want a new, unique id.
That's a nice solution, but unfortunately, it's runtime, not compiletime.
We use perl scripts to modify a .h file during the build. Shell scripts would work just as nice, if your using windows then cygwin is your friend.

with vs.net pre and post build steps can be useful to you in implementing this!

Cheers
Chris
CheersChris
What do you need it for?
The addresses of global variables are unique (assigned by the linker), and can safely be converted into an integer by casting it to intptr_t.
It's probably the easiest solution but also fairly limited.
if all you need is a guid then use the prebuild stage to call guidgen and copy this guid into a predetermined .h file.

Cheers
Chris
CheersChris
Thanks for the replies,

I'm currently writing a small library for use by other programmers working on the same project. Basically put, I've written all of the core parts, and only classes of functions [eg classes with only a void Foo();] need to be written by the other programmers.

What my system currently does [through the (mis)use of template specialisation] is allows them to write arbitrarily identified code - without bothering with any class declarations etc. My system picks them up at runtime and the application can immediately access them. There are other benefits that I won't go into, but the system works perfectly.

For example, the other programmers may write:

FC<1>::Foo()
{
//stuff goes here.
};

and this will immediately become available to the application (and be used by the application) after the next compile. However, if there are two FC classes which have template parameter <1> then the app won't compile.

I basically want to provide a simple way to generate unique IDs for these templates (and so a compiletime option is the only way to go). And there are potentially several hundred of these being written - so a manual solution doesn't really cut it.

Ah well, looks like a prebuild step to replace the __GLOBALCOUNT__ occurrences with a number, and a postbuild step to restore the old files is the way to go...

--CJM
The __COUNTER__ counter macro doesn't work? I don't see why it wouldn't, it sounds like that this kind of thing is what it was made for.
well maybe typeid can help..
#include <iostream>template <typename T>struct id{	static const int Id;};template <typename T>const int id<T>::Id = reinterpret_cast<int>(typeid(id).name());struct foo : id<foo>{};struct bar : id<bar>{};int main(void){	std::cout << "foo.Id == " << foo::Id << "\n"		<< "bar.Id == " << bar::Id << "\n";	return 0;}
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
You don't actually need unigue identifiers across source files. Just always declare the class inside an anonymous namespace.

file1.cpp
namespace {  FC<1>::Foo() {}}


file2.cpp
namespace {  FC<1>::Foo() {} //No problem!}


You only need unigue identifiers within a single cpp file. Even if the types look like they would collide, the anonymous namespaces keep the declarations from leaking out.

This topic is closed to new replies.

Advertisement