finding offset of a class member at compile time

R

Rahul

Hi,

Is there a way to find the offset of a class member at compile time.
e.g. class A{ int i; int j; char c; };

Here the offset of c = 8 bytes from the start of an object of A
(assuming 4 byte int). Can it be done at compile time.

Thanks in advance
 
G

Geo

Rahul said:
Hi,

Is there a way to find the offset of a class member at compile time.
e.g. class A{ int i; int j; char c; };

Here the offset of c = 8 bytes from the start of an object of A
(assuming 4 byte int). Can it be done at compile time.

Thanks in advance

Have you tried offsetof() ?
 
R

Rahul

offset of will do ((A*)0)->i which will happen at run time (not
compile time). But i want to know it at compile time only.

something like &A::i would have been better, but that also dosn't seem
to rum at compile time.
 
P

peter koch

Rahul skrev:
offset of will do ((A*)0)->i which will happen at run time (not
compile time). But i want to know it at compile time only.

How offsetof does its stuff is an implementation detail, but it will
always be a compile-time result. Your problem is another as offsetof is
defined for POD types only. But why do you want to know such stuff in
the first place? Answering that question might give way to the "real"
solution.

/Peter
 
R

Rahul

offset of is not giving the result at compile time.

The class is a POD, which has lots of members, the problem is that the
members have to be in a order (at least some of them, well its very
cryptic, but thats how the code has been written)

So to ensure that if somebody changes the class, he dosn't mess up the
order.
I m using a compile time macro, which creates an array of size (offset
(last_member-first_member)) to ensure that last_member is indeed
defined in the last.
 
N

Nindi

Rahul said:
offset of is not giving the result at compile time.

The class is a POD, which has lots of members, the problem is that the
members have to be in a order (at least some of them, well its very
cryptic, but thats how the code has been written)

So to ensure that if somebody changes the class, he dosn't mess up the
order.
I m using a compile time macro, which creates an array of size (offset
(last_member-first_member)) to ensure that last_member is indeed
defined in the last.

Probably not the best solution But I think something like the may work

struct {
struct {
struct {
int a;
}A;
int b;
}B;
double c
}C:
char d;
};
 
N

Nindi

Rahul said:
offset of is not giving the result at compile time.

The class is a POD, which has lots of members, the problem is that the
members have to be in a order (at least some of them, well its very
cryptic, but thats how the code has been written)

So to ensure that if somebody changes the class, he dosn't mess up the
order.
I m using a compile time macro, which creates an array of size (offset
(last_member-first_member)) to ensure that last_member is indeed
defined in the last.

Probably not the best solution But I think something like the may work

struct {
struct {
struct {
int a;
}A;
int b;
}B;
double c
}C:
char d;
}D;
 
N

Nindi

Rahul said:
offset of is not giving the result at compile time.

The class is a POD, which has lots of members, the problem is that the
members have to be in a order (at least some of them, well its very
cryptic, but thats how the code has been written)

So to ensure that if somebody changes the class, he dosn't mess up the
order.
I m using a compile time macro, which creates an array of size (offset
(last_member-first_member)) to ensure that last_member is indeed
defined in the last.

Probably not the best solution But I think something like the may work

struct {
struct {
struct {
int a;
}A;
int b;
}B;
double c
}C:
char d;
}D;
 
P

peter koch

Rahul skrev:
offset of is not giving the result at compile time.

In that case your C++ compiler is nonconforming. To be nonconforming in
this area is somewhat surprising, so I do believe you are wrong here.

NB. an expression such as size_t(&((A*)0)->i)) is a compile time
expression.

/Peter
[snip]
 
R

Rahul

I am using gcc version 3.4.5.
I don;t know if it confirms to the standard or not.

But ((A*)0)-> either using offsetof or explicitly is happening at run
time only, otherwise my COMPILE_TIME_ASSERT would have failed because
of -ve size array definition.

But at run time its printing the difference correctly (when i am doing
(first_member-last_member) and vice versa also.
 
A

Alf P. Steinbach

* Rahul:
I am using gcc version 3.4.5.
I don;t know if it confirms to the standard or not.

But ((A*)0)-> either using offsetof or explicitly is happening at run
time only, otherwise my COMPILE_TIME_ASSERT would have failed because
of -ve size array definition.

But at run time its printing the difference correctly (when i am doing
(first_member-last_member) and vice versa also.

The bugs are in your code.

Read the FAQ on how to post a question about code that doesn't work
correctly.

Then do as the FAQ says.
 
N

Nindi

Rahul said:
Hi,

Is there a way to find the offset of a class member at compile time.
e.g. class A{ int i; int j; char c; };

Here the offset of c = 8 bytes from the start of an object of A
(assuming 4 byte int). Can it be done at compile time.

Thanks in advance

How about this, it works for me. I employ typelists, you just need to
put a typelist in your class, its not ver intrusive because the typedef
is a compile time object.

#include<iostream>
#include<cmath>


using namespace std;

struct null_type{};

template<class TYPE1,class TYPE2>
struct TypeList{
typedef TYPE1 Head;
typedef TYPE2 Tail;
};


template<class TYPE,unsigned long i>
struct At {
typedef typename At<typename TYPE::Tail,i-1>::type type;

};

template<class TYPE>
struct At<TYPE,0> {
typedef typename TYPE::Head type;

};


template <class TLIST ,unsigned long i>
struct GetSize{
enum {value = sizeof(typename At<TLIST,i>::type) +
GetSize<TLIST,i-1>::value};
};

template <class TLIST>
struct GetSize<TLIST,0> {
enum {value = sizeof(typename At<TLIST,0>::type)};
};



#define TYPELIST_1(type) TypeList<type,null_type>
#define TYPELIST_2(type1,type2) TypeList<type1,TYPELIST_1(type2) >
#define TYPELIST_3(type1,type2,type3)
TypeList<type1,TYPELIST_2(type2,type3) >
#define TYPELIST_4(type1,type2,type3,type4)
TypeList<type1,TYPELIST_3(type2,type3,type4) >

struct A {
typedef TYPELIST_4(int,double,char,unsigned long) theTypeList;
int i;
double x;
char ch;
unsigned long ul;
};


int main() {

cout << GetSize<A::theTypeList,2>::value;

}
 
F

Frederick Gotham

Rahul:
Hi,

Is there a way to find the offset of a class member at compile time.
e.g. class A{ int i; int j; char c; };

Here the offset of c = 8 bytes from the start of an object of A
(assuming 4 byte int). Can it be done at compile time.

Thanks in advance


If you're working with a POD, then simply use the "offsetof" macro. If it
doesn't yield a compile-time constant, then you have a K++ compiler.

If working with a non-POD, then I think the only portable method would be to
create an object of it, e.g.:

SomeType obj;

size_t i = (char*)&obj.c - (char*)&obj;

, but this won't give you a compile-time constant.
 
H

Howard

Rahul said:
I am using gcc version 3.4.5.
I don;t know if it confirms to the standard or not.

But ((A*)0)-> either using offsetof or explicitly is happening at run
time only, otherwise my COMPILE_TIME_ASSERT would have failed because
of -ve size array definition.

Sounds like your COMPILE_TIME_ASSERT isn't written correctly. But you
haven't shown that code, so that's just a guess. (And I have _no_ idea what
the heck you mean by "-ve size array definition"!)
But at run time its printing the difference correctly (when i am doing
(first_member-last_member) and vice versa also.

Show the code!

-Howard
 
R

Rahul

Its this,

#define COMPILE_TIME_ASSERT(expr) do \
{ \
int temp[(expr) != 0 ? 1 : -1]; \
(void)(temp);\
} while(0)

So the following will casuse a compile time error.
COMPILE_TIME_ASSERT(2-2);
 
S

Serge Paccalin

Le 15.11.2006 05:36, :
Its this,

#define COMPILE_TIME_ASSERT(expr) do \
{ \
int temp[(expr) != 0 ? 1 : -1]; \
(void)(temp);\
} while(0)

So the following will casuse a compile time error.
COMPILE_TIME_ASSERT(2-2);

Try this one:

#define CAT__(A,B) A ## B
#define CAT_(A,B) CAT__(A,B)
#define COMPILE_TIME_ASSERT(expr) \
typedef int CAT_(CTA_DummyType,__LINE__)[(expr) ? 1 : -1]

Note that the first CAT__ has two underscores and the second only one.

--
___________
_/ _ \_`_`_`_) Serge PACCALIN -- sp ad mailclub.net
\ \_L_) Pour bien répondre avec Google, ne pas cliquer
-'(__) « Répondre », mais « Afficher les options »,
_/___(_) puis cliquer « Répondre » (parmi les options).
 
R

red floyd

Serge said:
Le 15.11.2006 05:36, :
Its this,

#define COMPILE_TIME_ASSERT(expr) do \
{ \
int temp[(expr) != 0 ? 1 : -1]; \
(void)(temp);\
} while(0)

So the following will casuse a compile time error.
COMPILE_TIME_ASSERT(2-2);

Try this one:

#define CAT__(A,B) A ## B
#define CAT_(A,B) CAT__(A,B)
#define COMPILE_TIME_ASSERT(expr) \
typedef int CAT_(CTA_DummyType,__LINE__)[(expr) ? 1 : -1]

Note that the first CAT__ has two underscores and the second only one.

That's unkosher. Any identifier with two consecutive underscores is
reserved to the implementation. Use CAT1_ instead.
 
H

Howard

Rahul said:
Its this,

#define COMPILE_TIME_ASSERT(expr) do \
{ \
int temp[(expr) != 0 ? 1 : -1]; \
(void)(temp);\
} while(0)

So the following will casuse a compile time error.
COMPILE_TIME_ASSERT(2-2);

(It would help if you'd follow the newsgroup guidelines, and quote what
you're responding to.)

How are you using this macro? You haven't shown the code using this, or the
structure you're using it on. You should always post _complete_ information
here, or else we're left groping in the dark.

Why are you using this declaration?:
int temp[(expr) != 0 ? 1 : -1];

Your code appears to check for inequality, as if all you want is for the two
numbers to be different. I thought you wanted to be sure the _order_ of the
members was correct. How are you doing that? What good does it do to only
accept _unequal_ values? (Hint: show the code!)

Anyway...

I did the following test, and it correctly tells me whether two members are
in the expected order or not:

struct TS1
{
// ok, correct order (a before b)
int a;
char b;
};

struct TS2
{
// not ok, wrong order (a after b)
char b;
int a;
};

#define COMPILE_TIME_ASSERT2(expr) do \
{ \
int temp[(expr)]; \
(void)(temp);\
} while(0)

int main()
{
COMPILE_TIME_ASSERT2(offsetof(TS1,b)-offsetof(TS1,a)); // ok
COMPILE_TIME_ASSERT2(offsetof(TS2,b)-offsetof(TS2,a)); // not ok

// ...
}

That code accepts TS1 fine, but for TS2 it reports that I can't have an
array larger than ffffffff bytes. So there's apparently a signed/unsigned
issue here. If I change the array definition like this:

int temp[(long)(expr)]; \

then I get the expected "negative subscript" error for TS2.

So, I think I've shown that offsetof is (at least with my compiler) a
compile-time value, eh? Try my code on your compiler. If it still fails
(by not causing an error), then you've got a non-compliant compiler.

-Howard
 
S

Serge Paccalin

Le 15.11.2006 16:44, :
That's unkosher. Any identifier with two consecutive underscores is
reserved to the implementation. Use CAT1_ instead.

OK, I didn't know that. I thought that only identifiers starting with
underscores (like __CAT or _EMAIL) were a problem.

--
___________
_/ _ \_`_`_`_) Serge PACCALIN -- sp ad mailclub.net
\ \_L_) Pour bien répondre avec Google, ne pas cliquer
-'(__) « Répondre », mais « Afficher les options »,
_/___(_) puis cliquer « Répondre » (parmi les options).
 

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

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,690
Members
48,796
Latest member
Greg L.

Latest Threads

Top