views:

154

answers:

2

Hi!

I am migrating a project from Linux to Xcode and I encountered a "version" problem..

I need a unique identifier at compile time for my dynamic stuff, on linux I was using the __ COUNTER__ preprocessor, but it seems that the gcc 4.2 used in Xcode doesn't know about __ COUNTER__ yet...
So, I was wondering what I could do to solve this?
I can upgrade the GCC to 4.3(which understands __ COUNTER_), by using the macports.org or something like that... I am very noob on OSX and not very good on linux =[
or find another way to accomplish this, in the case, a method to give the function/variable an unique identifier. I tried with _
LINE__ but after few days, you end up declaring stuff on the same line on different files, and playing with that is just not that produtive...

Any help is appreciated!

Thanks,
Jonathan

+1  A: 

I need to catalog all classes used in a project, so these classes can be created on the fly from within a factory [...]

Short of using RTTI (which isn't a bad idea if you are allowed to do this; boost::any does this), how about just using the string for the class names? You can retrieve this through a macro.

#include <iostream>
#include <string>
using namespace std;

template <class T>
const char* my_type_id()
{
    return "Unknown";
}

#define REGISTER_TYPE(some_type)            \
    template <> inline                      \
    const char* my_type_id<some_type>()     \
    {                                       \
        return #some_type;                  \
    }

REGISTER_TYPE(int)
REGISTER_TYPE(std::string)

int main()
{
    // displays "int"
    cout << my_type_id<int>() << endl;

    // displays "std::string"
    cout << my_type_id<string>() << endl;

    // displays "Unknown" - we haven't registered char
    cout << my_type_id<char>() << endl;
}

Nicest thing with this approach is that you don't have to worry about problems across translation units or modules with this approach. Only thing you have to watch out for is name conflicts, in which case you can specify a namespace to help avoid them ("std::string" as opposed to simply "string", e.g.).

We use this solution as an alternative for boost::any which we provide through our SDK (and therefore can't use boost as it would require our users to have boost installed or for us to ship parts of boost in which case it could lead to conflicts for users who have different versions of boost installed). It's not as automatic as boost::any as it requires manual registration of supported types (closer to boost::variant in this regard), but doesn't require our SDK users to have RTTI enabled and works portably across module boundaries (I'm not sure if one can depend on RTTI to produce the same information across varying compilers, settings, and modules - I doubt it).

Now you can use these type-associated string IDs however you like. One example would be to use it to map creation functions to these string IDs so that you can create an instance of std::string, for example, through factory::create("std::string"); Note that this is a hypothetical case for demo purposes only as using a factory to create std::string would be rather odd.

A: 

@stinky472: I use a code close to what you wrote above...

My problem was that I was using a macro to declare the namespaces of a project, so by that, having the fullname of the class, like class c is in a::b::c.
What I did was changing my code to not rely on the namespaces itself, but add a new argument at the class macro declaration to tell what namespace it is using, like:

newclass(a::b, c): public d{

};

my problem with counter was that the namespaces were being used on lots of classes, thus, creating the same variable name within the namespaces macros, and by using the new way above, I don't need the counter anymore...

thanks for the help,
Jonathan

Jonathan