char* to literal return from static in-class method definition - willthe pointer always be the same?

A

avasilev

Hi all, and Happy new Year!

I have the following class method:

class MyClass
{
public:
static const char* typeName() { return "myClass";}
};
The pointer that this method returns serves as an unique identifier of
the class. Thus, it must not only point to the class name string, but
also the value of the pointer itself serfes as an UID.

My question is: Since this method is defined inside the class
declaration, in a header file, is it guaranteed that the same
'version' of the method will be called in all compilation units in my
application, and any call to the method will return exactly the same
pointer, or will there be different 'copies' of the method and string
literal in each compilation unit, and they will return a different
char* ?

Thanks in advance
Alex
 
V

Victor Bazarov

I have the following class method:

class MyClass
{
public:
static const char* typeName() { return "myClass";}
};
The pointer that this method returns serves as an unique identifier of
the class. Thus, it must not only point to the class name string, but
also the value of the pointer itself serfes as an UID.

My question is: Since this method is defined inside the class
declaration, in a header file, is it guaranteed that the same
'version' of the method will be called in all compilation units in my
application, and any call to the method will return exactly the same
pointer, or will there be different 'copies' of the method and string
literal in each compilation unit, and they will return a different
char* ?

Don't compare pointers. Compare the string contents. If you want to
ensure that the pointers are always the same, create an object and
return its address. There is no guarantee that two literals have the
same address if their contents match. It's *usually* the case since the
linker merges those. The language doesn't require it, though.

Probably better to do

class MyClass
{
public:
static char const* typeName() {
static const char name[] = "myClass"; return name; }
};

V
 
A

avasilev

Don't compare pointers.  Compare the string contents.  If you want to
ensure that the pointers are always the same, create an object and
return its address.  There is no guarantee that two literals have the
same address if their contents match.  It's *usually* the case since the
linker merges those.  The language doesn't require it, though.

Probably better to do

    class MyClass
    {
    public:
       static char const* typeName() {
          static const char name[] = "myClass"; return name; }
    };

Thanks, Vadim. Doesn't the same instance of a literal (as it appears
in code) map to a single instance of this literal embeded in the data
section of the executable? I.e. if there is only one place in code
where this literal is defined, shouldn't be there only one copy of it
in the data section of the executable, hence only one possible pointer
to it?
My worry is that if the method is defined in a header, then there may
exist multiple local copies of the method, hence multiple literals.
Wouldn't this hold true even if I use a static local variable, as you
propose? OTOH, a static local is defined by the language to be
singleton, and I should not care about how this is implemented... I
guess I am missing some knowledge about how in-class defined methods
are linked. Can you please shed some light on this?

Alex

I was considering what you proposed,
 
A

avasilev

Don't compare pointers.  Compare the string contents.  If you want to
ensure that the pointers are always the same, create an object and
return its address.  There is no guarantee that two literals have the
same address if their contents match.  It's *usually* the case since the
linker merges those.  The language doesn't require it, though.

Probably better to do

    class MyClass
    {
    public:
       static char const* typeName() {
          static const char name[] = "myClass"; return name; }
    };

Thanks, Victor. Doesn't the same instance of a literal (as it appears
in code) map to a single instance of this literal embeded in the data
section of the executable? I.e. if there is only one place in code
where this literal is defined, shouldn't be there only one copy of it
in the data section of the executable, hence only one possible pointer
to it?
My worry is that if the method is defined in a header, then there may
exist multiple local copies of the method, hence multiple literals.
Wouldn't this hold true even if I use a static local variable, as you
propose? OTOH, a static local is defined by the language to be
singleton, and I should not care about how this is implemented... I
guess I am missing some knowledge about how in-class defined methods
are linked. Can you please shed some light on this?

As for comparing the strings, not the pointers, there is a performance
penalty that is unacceptable in my case - this is a type checking
mechanism that is executed every time an object is passed, so the
comparison is done quite frequently.
Alex
 
A

avasilev

Don't compare pointers.  Compare the string contents.  If you want to
ensure that the pointers are always the same, create an object and
return its address.  There is no guarantee that two literals have the
same address if their contents match.  It's *usually* the case since the
linker merges those.  The language doesn't require it, though.

Probably better to do

    class MyClass
    {
    public:
       static char const* typeName() {
          static const char name[] = "myClass"; return name; }
    };

Let me clarify a bit more on the use case. I actually have only one
place in code where the literal is - namely the typeName()method. The
class can be regarded as a factory, which creates objects, which have
a char pointer field, which the factory assigns to the return value of
typeName(). Later, when a function is called, taking such an object as
argument, it does type checking by calling typeName() of the factory,
and comparing the returned pointer to the object's field.

Alex
 
I

Ian Collins

On 01/ 4/12 08:17 AM, avasilev wrote:

Please don't snip attributions.
Don't compare pointers. Compare the string contents. If you want to
ensure that the pointers are always the same, create an object and
return its address. There is no guarantee that two literals have the
same address if their contents match. It's *usually* the case since the
linker merges those. The language doesn't require it, though.

Probably better to do

class MyClass
{
public:
static char const* typeName() {
static const char name[] = "myClass"; return name; }
};

Let me clarify a bit more on the use case. I actually have only one
place in code where the literal is - namely the typeName()method. The
class can be regarded as a factory, which creates objects, which have
a char pointer field, which the factory assigns to the return value of
typeName(). Later, when a function is called, taking such an object as
argument, it does type checking by calling typeName() of the factory,
and comparing the returned pointer to the object's field.

That's why Victor suggested a local static object: the address will be
unique.
 
G

Goran

Hi all, and Happy new Year!

I have the following class method:

class MyClass
{
public:
  static const char* typeName() { return "myClass";}};

The pointer that this method returns serves as an unique identifier of
the class. Thus, it must not only point to the class name string, but
also the value of the pointer itself serfes as an UID.

My question is: Since this method is defined inside the class
declaration, in a header file, is it guaranteed that the same
'version' of the method will be called in all compilation units in my
application, and any call to the method will return exactly the same
pointer, or will there be different 'copies' of the method and string
literal in each compilation unit, and they will return a different
char* ?

I just came in to mention the elephant in the room: typeid and
type_info. If you are in some sort of (extremely, I would say)
constrained environment, and you want to compile without RTTI, then
why a string? Wouldn't an enum be better then, or, if you don't want a
compile-time dependency, an integral?

Goran.
 
A

avasilev

I just came in to mention the elephant in the room: typeid and
type_info. If you are in some sort of (extremely, I would say)
constrained environment, and you want to compile without RTTI, then
why a string? Wouldn't an enum be better then, or, if you don't want a
compile-time dependency, an integral?

Goran.

Two reasons - for int or enum, i would need to define them manually,
and take care for them to be unique (i will need to add types later).
A pointer is automatically unique. And second - easier for debugging -
I can always print the class id as a string, if needed. I avoided
using RTTI for the reason you mentioned - I dint want to depend on C+
+'s RTTI. Not until they make it more useful :)
 
V

Victor Bazarov

I just came in to mention the elephant in the room: typeid and
type_info. If you are in some sort of (extremely, I would say)
constrained environment, and you want to compile without RTTI, then
why a string? Wouldn't an enum be better then, or, if you don't want a
compile-time dependency, an integral?

<shrug> I think that strings are more attractive because they carry that
"humanly readable" trait... But the OP can have a different reason, of
course.

V
 
G

Goran

Two reasons - for int or enum, i would need to define them manually,
and take care for them to be unique (i will need to add types later).
A pointer is automatically unique. And second - easier for debugging -
I can always print the class id as a string, if needed. I avoided
using RTTI for the reason you mentioned - I dint want to depend on C+
+'s RTTI. Not until they make it more useful :)

Key question is __why__ are you avoiding RTTI? If for size/speed, it's
already pretty tight. I don't believe it's implementation is much
bigger than your class name: it __is__ class name and a couple of
pointers (e.g. guess vtable and possibly nothing else). Further, I
would guess that any type_info instances that aren't used in code
itself would not be linked in. If that's the case, if you are in a
very constrained environment, then, (aside of class name being
wasteful), you're losing automatic elimination of unused type_info-s.

Finally, typeName(), the way you made it, is akin to following errors:

1.
class whatever_refactored_name { static const char* typeName()
{ return "whatever" } };

2.
class base { static const char* typeName() { return "base" } };
class derived : public base { /*Whoops, I forgot typeName*/ };

3.
struct base { static const char* typeName() { return "base"; } virtual
~base() };
struct derived : public base { static const char* typeName() { return
"derived"; } };
void f(const base& b, const derived& d)
{
if (b.typeName()==d.typeName())
{ /* Should get here, right? */ }
}
void g()
{
f(derived(), derived());
}

I believe that what you should rather be doing is either tightest
possible solution (int, or a char, even), either existing RTTI. And if/
when it's not enough, add your own bits.

Goran.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top