This question already has answers here:
typedef struct vs struct definitions [duplicate]
(12 answers)
Closed 8 years ago.
In a few places in the code I have a struct definition that looks like this:
typedef struct tagNameOfStruct{
//some methods and members
}T_NameOfStruct, * PT_NameOfStruct, FAR LPT_NameOfStruct;
typedef struct tagNameOfStructLists{
//some methods and members
}T_NameOfStructLists, * PT_NameOfStructLists, FAR LPT_NameOfStructLists;
typedef pair<T_NameOfStruct, T_NameOfStructLists> CStructPair;
typedef map<T_NameOfStruct, T_NameOfStructLists> CStructMap;
Than I see that inside a method within a loop the following line of code
T_NameOfStruct instance;
T_NameOfStructLists listInstance;
m_MapInstance.insert(CStructPair(instance, listInstance));
//structMapInstance is a members of method class of type CStructMap
That instance is being inserted to data-structure which is used outside the scope of the function.It is passed to the data-structure by reference.
Shouldn't instance die when we leave the function scope?
What does the last line of the struct definition mean?
Edit ---- Why this is not a duplicate, please reopen---- :
The * PT_NameOfStruct, FAR LPT_NameOfStruct in the struct definition are different from the question you guys linked too. Also there is the issue of the passing the instance by ref while it is defines on the method stack. The strange thing is that the code works so I'm wondering what I'm missing here. Why don't I get an exception while trying to access destroyed objects in a different function which iterates over the data structure.
Still think it's a duplicate?
Shouldn't instance die when we leave the function scope?
Yes. If the code you haven't shown us actually uses a reference to it after that, then it's wrong. But since we can't see it, we can only guess whether or not it does that.
UPDATE: Now you've shown us what's actually happening, it's being passed to map::insert, which stores a copy of its argument (even though it takes the argument by reference). There's no problem when instance itself is destroyed, assuming it has valid copy semantics.
What does the ending of the struct definition mean?
It declares:
a class called tagNameOfStruct.
an alias for the class type, called T_NameOfStruct. In C++ this is completely pointless; in C, some people have a bad habit of doing that to avoid typing struct when specifying the type.
an alias for a pointer to the type, called PT_NameOfStruct. This is an even worse idea than the first typedef, since it hides the important information that something is a pointer.
an alias for an obsolete "far" pointer to the type, called LPT_NameOfStruct. That's a hangover from 16-bit platforms; on a modern platform it will be the same as the regular pointer type.
Don't use this as a model for how to declare class types. It's better to keep it simple:
class NameOfStruct { // or "struct", if you want members to be public by default
// members
};
NameOfStruct instance; // No need for a typedef
NameOfStruct * pointer; // Make it clear that it's a pointer
struct tagNameOfStruct{
In C++, struct tags have equivalent status to typedefs. Not so in C.
T_NameOfStruct
This is another and better name for tagNameOfStruct.
*PT_NameOfStruct
This is a typedef for a pointer to NameOfStruct.
FAR LPT_NameOfStruct;
This is an obsolete name for a FAR pointer to NameOfStruct, given that near and far pointers have meant the same thing since Windows 95 as far as I can see. Note that this is because of the preceding * in the preceding typename, which carries over to this one because of C's strange pointer syntax.
The only things you need to worry about here are NameOfStruct, which is a typedef for the struct itself, and PT_NameOfStruct, which is a pointer to it. The rest is fluff.
That instance is being inserted to data-structure which is used outside the scope of the function. It is passed to the data-structure by reference.
Shouldn't instance die when we leave the function scope?
Yes. You have found a bug.
What does the ending of the struct definition mean?
'The ending of the struct definition' means that this is the end of the struct definition. What else would it mean? Did you mean the ending of the declaration? Did you mean everything I've stated above?
In addition to the above answers,
struct s
{
}
In above struct definition you can use as follows
in c for declaring instance you should do like this
struct s instance1;
in c++ you should define as follows
struct s instance1; (or)
s instance1;
Both are valid in c++.
In c instead of using struct s at all area you can use typedef for simplification.
Related
This question already has an answer here:
I can't understand this line - dereferencing an address of private member variable or what?
(1 answer)
Closed 6 years ago.
I stumbled across this question, which had an answer that used an odd construct:
typedef std::queue<int> Q;
typedef Q::container_type C;
C & get (Q &q)
{
struct hack : private Q {
static C & get (Q &q) {
return q.*&hack::c;
}
};
return hack::get(q);
}
I generally follow that q has access to its own c member that is being referenced by the get function. But, I am at a loss to clearly explain it. What is happening exactly with the .*&, and why is it allowed?
typedef std::queue<int> Q;
Q is a queue adapted container.
typedef Q::container_type C;
C is the underlying container of the Q -- which is a deque<int>.
C & get (Q &q) {
get takes a queue and returns a deque. In fact it returns the deque that the queue wraps: by conventional means, this is not possible.
struct hack : private Q {
hack is a type local to the function. It inherits from Q and has only one static member function. From its name, you may suspect it is a hack. You are right.
No hack is ever instantiated.
static C & get (Q &q) {
hack::get has the same signature as get itself. In fact we delegate all of the work of get to this method.
return q.*&hack::c;
this line needs to be broken down. I will do it in more lines:
using mem_ptr_t = C Q::*; // aka typedef C Q::*mem_ptr_t;
mem_ptr_t c_mem_ptr = &hack::c;
C& ret = q.*c_mem_ptr;
return ret;
The first line defines the type of a member pointer to a field of type C within a Q. Both the C++11 and C++03 ways of naming this type are ugly.
The second line gets a member pointer to the field c in Q. It does this through the hole in the type system of C++. &hack::c is logically of type C hack::* -- a pointer to a member of type C within a class of type hack. In fact, that is why we can access it in a static member of hack. But the c in question is actually in Q, so the actual type of the expression in C++ is C Q::*: a pointer to a member variable of Q.
You cannot directly get this member pointer within hack -- &Q::c is illegal, but &hack::c is not.
You can think of member pointers as 'typed offsets' into another type: &hack::c is the "offset" of c within Q together with knowing it is of type C. Now this isn't really true -- it is some opaque value that tells the compiler how to get c from Q -- but it helps to think about it that way (and it may be implemented that way in simple cases).
We then use this member pointer together with a Q& to get the c out of the Q. Getting a member pointer is constrained by protected: using it is not! The way we do it is with operator .*, which is the member dereference operator, which you can pass either member function pointers or members on the right, and class instances on the left.
instance .* member_ptr is an expression that finds the member "pointed to" by member_ptr within the instance. In the original code, everything was done on one line:
instance .* &class_name::member_name
so it looked like there was an operator .*&.
}
};
and then we close up the static method and hack class, and:
return hack::get(q);
}
call it. This technique gives access to protected state: without it, protected members can only be accessed in child classes of the same instance. Using this, we can access protected members of any instance, without violating any bit of the standard.
It's a hack, as the nomenclature indicates.
.* takes an object on the left side, and a member pointer on the right side, and resolves the pointed-to member of the given object. & is, of course, the referencing operator; &Class::Member returns a member pointer, which cannot by itself be dereferenced but which can be used with the .* and ->* operators (the latter being the wackiest of all C++ operators). So obj .* &Class::Member has exactly the same effect as obj.Member.
The reason this more complicated version is being used comes down to a loophole in protection semantics; basically, it allows access to protected members of a base class object, even if the object is not of the same type as the class doing this dirty hack.
Personally, I think the trick is too clever by half. I'd ordinarily* write such code as:
struct hack : private Q {
static C & get (Q &q) {
return static_cast<hack &>(q).c;
}
};
Which is technically slightly less safe, but doesn't obscure what's going on.
.* Well, ordinarily I'd avoid writing such a thing at all. But I literally did this earlier today, so I can't really throw stones.
Rather surprised to find this question not asked before. Actually, it has been asked before but the questions are VERY DIFFERENT to mine. They are too complicated and absurd while I'll keep it simple and to the point. That is why this question warrants to be posted.
Now, when I do this,
struct A {
int a = -1;
};
I get the following error:
ANSI C++ forbids in-class initialization of non-const static member a
Now, along with the workaround can someone please tell me THE BEST way of initializing a struct member variable with a default value?
First, let's look at the error:
ANSI C++ forbids in-class initialization of non-const static member a
Initialization of a true instance member, which resides within the memory of an instance of your struct is the responsibility of this struct's constructor.
A static member, though defined inside the definition of a particular class/struct type, does not actually reside as a member of any instances of this particular type. Hence, it's not subject to explaining which value to assign it in a constructor body. It makes sense, we don't need any instances of this type for the static member to be well-initialized.
Normally, people write member initialization in the constructor like this:
struct SomeType
{
int i;
SomeType()
{
i = 1;
}
}
But this is actually not initialization, but assignment. By the time you enter the body of the constructor, what you've done is default-initialize members. In the case of a fundamental type like an int, "default-initialization" basically boils down to "eh, just use whatever value was in those bytes I gave you."
What happens next is that you ask i to now adopt the value 1 via the assignment operator. For a trivial class like this, the difference is imperceptible. But when you have const members (which obviously cannot be tramped over with a new value by the time they are built), and more complex members which cannot be default-initialized (because they don't make available a visible constructor with zero parameters), you'll soon discover you cannot get the code to compile.
The correct way is:
struct SomeType
{
int i;
SomeType() : i(1)
{
}
}
This way you get members to be initialized rather than assigned to. You can initialize more than one by comma-separating them. One word of caution, they're initialized in the order of declaration inside your struct, not how you order them in this expression.
Sometimes you may see members initialized with braces (something like i{1} rather i(c)). The differences can be subtle, most of the time it's the same, and current revisions of the Standard are trying to smooth out some wrinkles. But that is all outside the scope of this question.
Update:
Bear in mind that what you're attempting to write is now valid C++ code, and has been since ratification of C++11. The feature is called "Non-static data member initializers", and I suspect you're using some version of Visual Studio, which still lists support as "Partial" for this particular feature. Think of it as a short-hand form of the member initialization syntax I described before, automatically inserted in any constructor you declare for this particular type.
You could make a default constructor
struct A {
A() : a{-1} {}
int a;
};
Say I have some data allocated somewhere in my program, like:
some_type a;
and I want to wrap this data in a class for access. Is it valid to say,
class Foo {
private:
some_type _val;
public:
inline void doSomething() { c_doSomething(&_val); }
}
Foo *x = reinterpret_cast<Foo *>(&a);
x->double();
The class has no virtual functions, and only includes a single data item of the type I'm trying to wrap. Does the C++ standard specify that this reinterpret_cast is safe and valid? sizeof(Foo) == sizeof(some_type), no address alignment issues, or anything? (In my case, I'd be ensuring that some_type is either a primitive type like int, or a POD structure, but I'm curious what happens if we don't enforce that restriction, too - for example, a derived class of a UIWidget like a UIMenuItem, or something.)
Thanks!
Is it valid to say...
No, this is not valid. There are only a small number of types that a can be treated as; the complete list can be found in an answer I gave to another question.
Does the C++ standard specify that this reinterpret_cast is safe and valid?
The C++ Standards says very little about reinterpret_cast. Its behavior is almost entirely implementation-defined, so use of it is usually non-portable.
The correct way to do this would be to either
have a Foo constructor that takes a some_type argument and makes a copy of it or stores a reference or pointer to it, or
implement your "wrapper" interface as a set of non-member functions that take a some_type object by reference as an argument.
14882/1998/9.2.17:
"A pointer to a PODstruct
object, suitably converted using a reinterpret_cast, points to its initial
member (or if that member is a bitfield,
then to the unit in which it resides) and vice versa. [Note: There
might therefore be unnamed padding within a PODstruct
object, but not at its beginning, as necessary to
achieve appropriate alignment. ]"
So, it would be valid if your wrapper was strictly a POD in itself. However, access specifiers mean that it is not a strictly a POD. That said, I would be interested in knowing whether any current implementation changes object layout due to access specifiers. I think that for all practical purposes, you are good to go.
And for the case when the element is not a POD, it follows that the container is not a POD, and hence all bets are off.
Since your Foo object is already only valid as long as the existing a is valid:
struct Foo {
some_type &base;
Foo(some_type &base) : base (base) {}
void doSomething() { c_doSomething(&base); }
}
//...
Foo x = a;
x.doSomething();
You want to look up the rules governing POD (plain old data) types. If the C++ class is a POD type, then yes, you can cast it.
The details of what actually happens and how aliasing is handled are implementation defined, but are usually reasonable and should match what would happen with a similar C type or struct.
I happen to use this a lot in a project of mine that implements B+ trees in shared memory maps. It has worked in GCC across multiple types of Linux and BSDs including Mac OS X. It also works fine in Windows with MSVC.
Yes, this is valid as long as the wrapper type you are creating (Foo in your example) is a POD-type.
I have following two classes:
template <size_t size>
class Cont{
public:
char charArray[size];
};
template <size_t size>
class ArrayToUse{
public:
Cont<size> container;
inline ArrayToUse(const Cont<size+1> & input):container(reinterpret_cast<const Cont<size> &>(input)){}
};
I have three following lines of code at global scope:
const Cont<12> container={"hello world"};
ArrayToUse<11> temp(container);
char (&charArray)[11]=temp.container.charArray;
In totality of my code The only usage of "container" object is for initialization of an object of "ArrayToUse" class as mentioned and after initialization of "charArray" reference to "temp.container.charArray" I'll use that reference in rest of my code, now I'm wondering does compiler reserve memory for "container" object since that's got a temporary usage?
Any variable defined at global scope has memory reserved for it at compile time. That does not mean it's guaranteed to be properly initialized, but it's there all the same.
At link-time, Visual C++ offers the option to strip unused data and functions via /OPT - see here.
it totaly depends on your particular compiler so i'd say inspect the assembly and find out!
the compiler could optimize container out, or it could neglect to do so.
The compiler should create the container variable in the compiled object file. The linker is the one that can tell if it's needed or not (for an exported symbol, or from another compilation unit if declared extern).
But...
The type Cont<x> is unrelated to Cont<x+1>. You cannot depend on the memory of a member variable being layed out in similar fashions. Heck, you cannot even know if it looks the same, since there is this thing called 'template specialization':
// your code
template <size_t size>
class Cont{
public:
char charArray[size];
};
// my evil tweak
// I'm the worst compiler ever but I feel that this
// array would better be represented as a map...
template<> class Cont<12> {
std::map<int,char> charArray;
};
// your screwed up result
Cont<12> c12;
Cont<11>& c11( reinterpret_cast<Cont<11>&>(c12) );
char (&s11)[11] = c11.charArray; // points to the first byte of a list object...
EDIT -- #UncleBen's comment insinuates I'm overdoing here. And he's right.
according to wikipedia,
A pointer to a POD-struct
object, suitably converted using a
reinterpret cast, points to its
initial member and vice versa,
implying that there is no padding at
the beginning of a POD-struct.
So in this case,
where the charArray is the first member of a Cont<n>, and there are no non-POD members
there is no assignment operator, nor a destructor
It is safe.
Before I was trying to map my classes and namespaces, by using static calls I succeded and now I need to map the functions of my classes because they will be used dynamically.
Firstly I was thinking to hardcode in the constructor so I can assign a std:map with the string of the name of function pointing to the function itself.
for example:
class A{
int B(){
return 1;
}
};
int main(){
A *a = new A();
vector<string, int (*)()> vec;
vector["A.B"] = a.B;
}
By that I have mapped the function B on A class, I know that I only mapped the function the instance and thats B is not static to be globally mapped.
But thats what I need, at somepoint someone will give me a string and I must call the right function of an instance of a class.
My question is if I only can do that by hardcoding at the constructor, since this is a instance scope we are talking or if there is somehow a way to do this in the declaration of the function, like here for namespaces and classes:
Somehow register my classes in a list
If I understand you correctly, you want your map to store a pointer that can be used to call a member function on an instance, the value being chosen from the map at run time. I'm going to assume that this is the right thing to do, and that there isn't a simpler way to solve the same problem. Quite often when you end up in strange C++ backwaters it's a sign that you need to look again at the problem you think you have, and see whether this is the only way to solve it.
The problem with using an ordinary function pointer is that a non-static member function is not an ordinary function. Suppose you could point to a member function with an ordinary function pointer, what would happen when you dereferenced that pointer and called the function? The member function needs an object to operate on, and the syntax doesn't provide a way to pass this object in.
You need a pointer to member, which is a slightly obscure feature with relatively tricky syntax. While an ordinary pointer abstracts an object, a pointer to member abstracts a member on a class; the pointer specifies which class member should be called, but not which object to obtain the member from (that will be specified when the pointer is used). We can use it something like this:
class B;
class A
{
B some_function()
{ /* ... */ }
};
B (A::* myval)() = A::some_function;
Here myval is a variable that indicates one of the members of class A, in this case the member some_function (though it could point to any other member of A of the same type). We can pass myval round wherever we want (e.g. storing it in an STL container, as in your example) and then when we want to call the function, we specify the instance it should be called on in order to locate the function:
A some_a;
B newly_created_b = (some_a.*myval)();
This works for a particular case, but it won't solve your general issue, because member pointers contain the class they refer to as part of the definition. That is, the following two variables are of entirely different types:
B (Foo::* first_variable)() = Foo::some_function;
B (Bar::* second_variable)() = Bar::some_function;
Even though both functions can produce a B when called without arguments, the two values operate on different classes and therefore you can't assign a value of one type to a variable of the other type. This of course rules out storing these different types in a single STL container.
If you're committed to storing these in a container, you'll have to go with a functor-based solution like Charles Salvia proposes.
If I understand you correctly, you're going to have a class like:
struct Foo
{
int bar();
};
And the user will input a string like "Foo::bar", and from that string you need to call the member function Foo::bar?
If so, it's rather awkward to code a flexible solution in C++, due to the static type system. You can use an std::map where the key is a string, and the value is a member function pointer, (or std::mem_fun_t object), but this will only work on a single class, and only on member functions with the same signature.
You could do something like:
#include <iostream>
#include <map>
#include <functional>
struct Foo
{
int bar() { std::cout << "Called Foo::bar!" << std::endl; }
};
int main()
{
std::map<std::string, std::mem_fun_t<int, Foo> > m;
m.insert(std::make_pair("Foo::bar", std::mem_fun(&Foo::bar)));
Foo f;
std::map<std::string, std::mem_fun_t<int, Foo> >::iterator it = m.find("Foo::bar");
std::mem_fun_t<int, Foo> mf = it->second;
mf(&f); // calls Foo::bar
}
just found(using google) a topic to the same question I had with an answer.
What is the simplest way to create and call dynamically a class method in C++?
I didn't try it yet but makes sense, I will ask again later if it doesn't work
ty!
Joe
I must call the right function of an instance of a class.
You need to call a specific method on an existing instance, or you need to create an instance of the appropriate type and call the method?
If it's the former, then you need a std::map or similar that lets you look up instances from their names.
If it's the latter, that's basically what serialization frameworks need to do in order to create the correct type of object when de-serializing, the object that knows how to read the next bit of data. You might take a look at how the Boost serialization library handles it:
boost.org/doc/libs/1_40_0/libs/serialization/doc/serialization.html
Are you doing this in some kind of tight loop where you need the efficiency of a good map? If so, then member function pointers (as you linked to above) is a good way to go. (At least it is after you work around the problem #Tim mentioned of keeping member function pointers to different types in the same collection ... let the language abuse begin!)
On the other hand, if this is in code that's user-driven, it might be more legible to just be totally uncool and write:
if( funcName=="A.b" )
{
A a;
a.b();
} else
// etc etc etc
For the higher-performace case, you can supplement the same approach with a parse step and some integer constants (or an enum) and use a switch. Depending on your compiler, you might actually end up with better performance than using member function pointers in a map:
switch( parse(funcName) )
{
case A_b:
{
A a;
a.b();
}
break;
}
(Of course this breaks down if you want to populate your list of possibilities from different places ... for example if each class is going to register itself during startup. But if you have that kind of object infrastructure then you should be using interfaces instead of pointers in the first place!)