Paul Brettschneider wrote:
Quote:
Hello,
>
I have a global static array of structs and want to access a given
element using an identifier. I don't want to use the element subscript,
because it will change if I insert elements before the element I
want to access. In assembler I would simply add a label in front
of the element, but this doesn't work in C++.
>
The following programm snippet might explain what I want to do:
>
#include <iostream>
>
class A {
public:
const char *s;
};
>
static A array[] = {
{ "a" },
{ "b" },
// I wish I could just define a label to a given element like this,
// but this syntax is already used for designated inits (at least in gcc):
// element_c:
{ "c" },
{ "d" },
{ "e" },
{ "f" },
{ "g" },
};
>
int main()
{
// Access element "c"
std::cout << array[2].s << std::endl;
>
// Now I wish I could write it this:
// std::cout << element_c.s << std::endl;
>
// Or maybe:
// std::cout << array::element_c.s << std::endl;
>
return 0;
}
>
Is there a way to do this in C++ (maybe some preprocessor tricks)?
One C++ way to do this is via references. References can be initialized
by looking up the array using a special function or statically if you
know the index. If the definition of the reference is static then more
than likely the compiler will look it up directly.
As for creating linker labels, you're outa luck. There is very little
chance you can do that portably. There is nothing stopping you however
doing what you want using assembler if your platform supports it.
The code below would solve your issue, and is probably all I would do
until I knew that this solution raises a siginificant problem.
#include <iostream>
#include <cstring>
class A {
public:
const char *s;
bool CompKey( const char * str )
{
return strcmp( str, s ) == 0;
}
};
extern A & element_a;
extern A & element_c;
extern A & element_g;
static A array[] = {
{ "a" },
{ "b" },
// I wish I could just define a label to a given element like this,
// but this syntax is already used for designated inits (at least in gcc):
// element_c:
{ "c" },
{ "d" },
{ "e" },
{ "f" },
{ "g" },
};
template <typename T, int N>
char (&EndOfHelper( T (&)[N] ))[N];
#define EndOf(A) ((A)+sizeof(EndOfHelper(A)))
A & findA( const char * istr )
{
for ( A * i = array; i < EndOf( array ); ++ i )
{
if ( i->CompKey( istr ) )
{
return *i;
}
}
throw "Failed to kind key in array";
}
A & element_a = array[ 0 ];
A & element_c = findA( "c" );
A & element_g = findA( "g" );
int main()
{
// Access element "c"
std::cout << array[2].s << std::endl;
// Now I wish I could write it this:
// std::cout << element_c.s << std::endl;
// Or maybe:
// std::cout << array::element_c.s << std::endl;
return 0;
}