Accessing a Pointer to a pointer in C++ - c++

Hi I am using a 3rd party library in my iPhone application that uses C++ one of the methods i need to use returns a pointer to a pointer of a class. like follows.
DLL classAttributes** getAttributes();
I can successfully call the method and return the value into a pointer to a pointer like so;
classAttributes **attributes = cPPClass->getAttributes();
however i can't seem to access any of the methods on the class for example i know that the class has a function called getName(); but when i try calling it i get errors.
attributes->getName(); 'Request for member 'getName' in *attributes'; which is of non-class type 'attributes*''
I did some googling and found some stuff that said to access a pointer pointer address use the format
&(*attributes)->getName(); 'invalid uses of incomplete type 'struct attributes'
Any help would be much appreciated.
Thanks.

'invalid uses of incomplete type 'struct attributes' indicates that you need to #include the header file for it. It's only forward-declared at this point in your code.

What you probably want is a classAttributes*. Since you have a classAttribues** , you want to dereference it once to get to the classAttributes*.
(*attributes)
From there you can probably call the members of the class.
classAttributes **attributesArray = cPPClass->getAttributes();
classAttributes *attributesObject(*attributesArray);
attributesObject->getName();

First consider what you would do if the function returned a pointer to a classAttributes variable. In this case, you would simply do:
attributes->getName();
Since it's a pointer to a pointer, you must first dereference it and then use the -> operator:
(*attributes)->getName();
If this doesn't work, it may be a problem caused by the function not being implemented or by inheritance.

Without knowing more about the library, it's hard to say. But it could be returning an array of items:
attributes[0]->getName();
attributes[1]->getName();
The questionable part about my guess, though, is that there is no obvious way to know how many items there are.

By the looks of it, you'd probably have to do is this way (i.e. no ampersand):
(*attributes)->getName();
This is because dereferencing it once will give you a pointer to a struct, on which you can then use the -> operator. What's happening when you do &(*attributes) is that you're dereferencing the pointer, then getting the address of the object you have — in effect making it a no-op.

Related

QVariant wrapped pointers turn to null in QML

It seems like something is going wrong when pointer values transcend between C++ and QML world. I am using the plain old fromValue() and value() to convert to and from void *, and it does work as expected as long as the variant stays on the C++ side.
The moment it is returned to QML, it now resolves to null, and when passed back to C++, the variant type is changed from void * to std::nullptr_t and the value is null.
returning 0x3ba5b10 // created
converting to qvariant 0x3ba5b10 // converting
converted QVariant(void*, 0x3ba5b10) 0x3ba5b10 // now variant, testing value() - all good
qml: null // in qml
received QVariant(std::nullptr_t, (nullptr)) 0x0 // back in c++
I am using:
Q_DECLARE_METATYPE(void*)
qRegisterMetaType<void*>();
Any clue as to what is going on here?
Edit: it keeps even more strange, I get it to work by casting the pointer values to 64 bit uint and back, but upon the transition to QML, the type info gets messed up, in C++ the variant is of type qulonglong, arriving back from QML it is now a double, hence the suspicion it might round something and mess up the pointer value.
Edit 2: note that the question is not about recommending practices but about why this doesn't work as expected and observed prior to reaching QML.
You don't need to register void*, rather use the metatype QMetaType::VoidStar.
Note that to register the metatype SomeCustomType*, you need to use an alias.
using SomeCustomTypePtr = SomeCustomType*;
Q_DECLARE_METATYPE(SomeCustomTypePtr)
qRegisterMetaType<SomeCustomTypePtr>();
Isn't even possible to do such declarations?
According to official documentation on Q_DECLARE_METATYPE(Type):
This macro makes the type Type known to QMetaType as long as it provides a public default constructor, a public copy constructor and a public destructor. It is needed to use the type Type as a custom type in QVariant.
This macro requires that Type is a fully defined type at the point where it is used.
Sounds strange that this works at least in C++ part.
Don't you think that it will be better and straight-forward solution to declare your type pointer instead of void*?

What is this C++ casting code doing?

Found here: https://github.com/tpaviot/oce/blob/master/src/BRepAdaptor/BRepAdaptor_Curve.cxx
The line I'm wondering about is:
((GeomAdaptor_Curve*) (void*) &myCurve)->Load(C,First,Last);
myCurve is already defined as a GeomAdaptor_Curve. So it looks like it's casting a pointer to myCurve as a void*, and then casting that as a GeomAdaptor_Curve*, and then dereferencing it and calling Load on it. What possible reason could there be for doing that, rather than simply calling myCurve.Load?
Note that statement appears in a const member function. So the type of &myCurve is actually GeomAdaptor_Curve const*. This appears to be an ugly and confusing way to say
const_cast<GeomAdaptor_Curve&>(myCurve).Load(C,First,Last);
and may have been made more complicated in order to "avoid" compiler warnings you would get from attempting to use a C-style cast to circumvent const.
The only reason I could think of would be to ensure that a variable of the type "subclass of GeomAdaptor_Curve" was forced to call the Load function of the super-class.
The cast to void*, then on to GeomAdaptor_Curve*, would guarantee the type was treated as the latter, regardless of its actual type.
Having looked into the code, I can't see where this is a possibility so it's likely that it's either legacy code or something they've put in for future expansion.
It may be worthwhile contacting the dbarbier user on GitHub as they appear to have sole responsibility for changes (based on history).
Although, since that piece of code seems to be in the earliest GitHub versions, the original author may be a better bet, if you can find them (see the file header for one Remi LEQUETTE).

xcode - "attempt to use a deleted function" - what does that mean?

I am writing a C++ library in Xcode 4.2.
One of my classes won't compile with this error:
attempt to use a deleted function
There is no specific indication what function it's talking about.
I don't want to post the class code here, but does anybody have any idea what this error means?
I had a similar message with threads (C++11). It turned out that I was passing the wrong number of parameters to the function called by the thread so the thread did not find any function suitable and gave that message.
To add to Carlos' answer, I had the right number of arguments but one of the arguments was being passed by reference. Adding ref() around the variable fixed it for me. See here.
In C++11 you can declare functions as deleted:
struct Foo {
Foo(const Foo &) = delete;
};
Attempting to use such a function is an error. The purpose of doing this is so that, in this example, copy construction of this type is not possible. This is a more direct replacement for the non-copyable trick used pre-C++11.
Also, there are rules in the C++ spec that lead to member functions being implicitly deleted.
The error is telling you that your program attempts to use a deleted function. You'll have to post the error you're getting for more detailed help.
For me It solved it when I passed "this" pointer as a parameter to the function.
For me, the issue was that one of the arguments was a pointer, and I passed NULL directly as an argument. To solve this, I simply created a new NULL pointer which I passed to the function as an l-value instead.

error C2064: term does not evaluate to a function taking 0 arguments

In some code I'm writing, I have the following line, which gives me error C2064:
rs_opCodes[cur_block]();
rs_opCodes is defined as such:
typedef void (rsInterpreter::*rs_opCode)();
rs_opCode rs_opCodes[NUM_OPCODES];
Does anyone know why I'm recieved error C2064?
You have to use the syntax of method pointer call, but you need an object to which make the actual call. Note that the typedef stablishes that you're defining pointers to a method of objects of type rsInterpreter, so you need an object of that type:
rsInterpreter r;
(r.*rs_opCodes[cur_block])();
However, the whole idea of this doesn't make much sense to me. You're writting an array of method pointers to be called in objects... I can't, at first thought, come up out of my mind of an usable example of this type of code...
You defined rs_opCode as a pointer to a member function (of class rsInterpreter).
To call such a beast, you need the sytax
(object.*rs_opCodes[cur_block])();
or
(pointer->*rs_opCodes[curr_block])();
You defined rs_opCode to be a method pointer but you are using it as function pointer.

(Obj) C++: Instantiate (reference to) class from template, access its members?

I'm trying to fix something in some Objective C++ (?!) code. I don't know either of those languages, or any of the relevant APIs or the codebase, so I'm getting stymied left and right.
Say I have:
Vector<char, sizeof 'a'>& sourceData();
sourceData->append('f');
When i try to compile that, I get:
error: request for member 'append' in 'WebCore::sourceData', which is of non-class type 'WTF::Vector<char, 1ul >& ()();
In this case, Vector is WTF::Vector (from WebKit or KDE or something), not STD::Vector. append() very much is supposed to be a member of class generated from this template, as seen in this documentation. It's a Vector. It takes the type the template is templated on.
Now, because I never write programs in Real Man's programming languages, I'm hella confused about the notations for references and pointers and dereferences and where we need them.
I ultimately want a Vector reference, because I want to pass it to another function with the signature:
void foobar(const Vector<char>& in, Vector<char>& out)
I'm guessing the const in the foobar() sig is something I can ignore, meaning 'dont worry, this won't be mangled if you pass it in here'.
I've also tried using .append rather than -> because isn't one of the things of C++ references that you can treat them more like they aren't pointers? Either way, its the same error.
I can't quite follow the error message: it makes it sound like sourceData is of type WTF:Vector<char, 1ul>&, which is what I want. It also looks from the those docs of WTF::Vector that when you make a Vector of something, you get an .append(). But I'm not familiar with templates, either, so I can't really tell i I'm reading that right.
EDIT:
(This is a long followup to Pavel Minaev)
WOW THANKS PROBLEM SOLVED!
I was actually just writing an edit to this post that I semi-figured out your first point after coming across a reference on the web that that line tells the compiler your forward declaring a func called sourceData() that takes no params and returns a Vector of chars. so a "non-class type" in this case means a type that is not an instance of a class. I interpreted that as meaning that the type was not a 'klass', i.e. the type of thing you would expect you could call like .addMethod(functionPointer).
Thanks though! Doing what you suggest makes this work I think. Somehow, I'd gotten it into my head (idk from where) that because the func sig was vector&, I needed to declare those as &'s. Like a stack vs. heap pass issue.
Anyway, that was my REAL problem, because I tried what you'd suggested about but that doesn't initialize the reference. You need to explicitly call the constructor, but then when I put anything in the constructor's args to disambiguate from being a forward decl, it failed with some other error about 'temporary's.
So in a sense, I still don't understand what is going on here fully, but I thank you heartily for fixing my problem. if anyone wants to supply some additional elucidation for the benefit of me and future google people, that would be great.
This:
Vector<char, sizeof 'a'>& sourceData();
has declared a global function which takes no arguments and returns a reference to Vector. The name sourceData is therefore of function type. When you try to access a member of that, it rightfully complains that it's not a class/struct/union, and operator-> is simply inapplicable.
To create an object instead, you should omit the parentheses (they are only required when you have any arguments to pass to the constructor, and must be omitted if there are none):
Vector<char, sizeof 'a'> sourceData;
Then you can call append:
sourceData.append('f');
Note that dot is used rather than -> because you have an object, not a pointer to object.
You do not need to do anything special to pass sourceData to a function that wants a Vector&. Just pass the variable - it will be passed by reference automatically:
foobar(sourceData, targetData);
Dipping your toes in C++ is never much fun. In this case, you've run into a couple of classic mistakes. First, you want to create an instance of Vector on the stack. In this case the empty () is interpreted instead as a declaratiton of a function called sourceData that takes no agruments and returns a reference to a Vector. The compiler is complaining that the resulting function is not a class (it's not). To create an instance of Vector instead, declare the instance without the () and remove the &. The parentheses are only required if you are passing arguments to the instance constructor and must be omitted if there are no arguments.
You want
Vector<char, sizeof 'a'> sourceData;
sourceData.append('f');
Vector<char, sizeof 'a'> outData; //if outData is not instantiated already
foobar(sourceData, outData);
This Wikipedia article gives a decent introduction to C++ references.