I am attempting to install a help browser starting from
http://www.walletfox.com/course/qhelpengineexample.php
For the line
tWidget->addTab(helpEngine->contentWidget(), tr("Contents"));
I receive error message
no known conversion from QHelpIndexWidget* to QWidget*
and really, if I make explicite casting with
tWidget->addTab((QWidget*)helpEngine->contentWidget(), tr("Contents"));
the program compiles and runs fine. What is going on here?
Most likely you forgot to #include <QHelpIndexWidget>.
Then the compiler can't deduct that a QHelpIndexWidget inherits from QWidget.
If you would try to access the QHelpIndexWidget*, like e.g.
qDebug() << helpEngine->indexWidget()->objectName();
without the include, you would get the better compiler error "QHelpIndexWidget is of incomplete type" or similar, which means that the type is forward declared, but the complete declaration is not accessible.
Additionally, I would suggest avoiding c-style casts and use static_cast<TYPE>(var) instead.
Related
I have an error that used to look like this in Objective-C
NSString * const JKConfigurationErrorDomain;
typedef NS_ENUM(NSInteger, JKConfigurationCode) {
JKConfigurationCodeUnknown,
JKConfigurationCodeSomethingBad,
JKConfigurationCodeParsing,
};
Now, this is ugly to use in Swift. But since Swift 4, we can use NSErrorDomain and NS_ERROR_ENUM to make the imported error much nicer in Swift:
NSErrorDomain const JKConfigurationErrorDomain;
typedef NS_ERROR_ENUM(JKConfigurationErrorDomain, JKConfigurationCode) {
JKConfigurationCodeUnknown,
JKConfigurationErrorSomethingBad,
JKConfigurationErrorParsing,
};
This means I can now do stuff in Swift like this:
if let myError = error as? JKConfigurationError, myError.code = .somethingBad {
// handle it
}
instead of having to cast error to NSError, then check its .domain then look at the .code which is an integer, etc.
So far, so good. But my library is called JKConfiguration and there is already a JKConfiguration object (the center piece of the library) in there and as soon as I start using JKConfiguration anywhere in the library code I get an error:
'JKConfiguration' is ambiguous for type lookup in this context
I don't get it, why? What does NSErrorDomain or NS_ERROR_ENUM do such that the type lookup becomes ambiguous and how can I fix it?
What I tried already:
use NS_SWIFT_NAME on the NS_ERROR_ENUM typedef and rename it to something else. Looking at the generated Swift header, the rename works, but doesn't solve the issue
Change the name of the error domain (and thus of the generated error type in Swift). Seems to work according to the generated Swift header, but the issue still persists. Why is that?
The issue is not, as I initially thought, in the name of the error domain. Nor is it a problem with the library name. It’s a problem of the error enum‘s name, in the example above: JKConfigurationCode.
What the Compiler does for the enum cases of an NS_ERROR_ENUM is two-fold:
use the name of the enum and remove that prefix from all enum cases before importing them to swift
create an enum with the given name to hold those cases. If the given name ends with Code remove that suffix.
So that last part is the issue. It means that NS_ERROR_ENUM(AnyDomainName, JKConfigurationCode) generates an enum in Swift to hold the error codes with the name JKConfiguration (without the Code) prefix. But that type already exists in my example, which leads to the ambiguity.
So the solution is to change
NS_ERROR_ENUM(JKConfigurationErrorDomain, JKConfigurationCode)
to
NS_ERROR_ENUM(JKConfigurationErrorDomain, JKConfigurationSomethingCode)
Or similar.
Don’t forget to update all the prefixes of your enum cases though, as it seems the compiler won’t find them if the prefixes don’t match the enum name.
Why doesn’t NS_SWIFT_NAME work to rename the enum?
Best I can tell, NS_SWIFT_NAME causes the type to be renamed but not the cases. This leads to an empty type (Swift chooses a struct in that case) being generated for the error code as Swift doesn’t seem to find the cases. And the original container for the enum cases still has the offending name.
Is it possible to somehow use hexadecimal numbers in a static method call in MSBuild? I've tried a few different variations, but I'm getting this error:
error MSB4186: Invalid static method invocation syntax:
"[MSBuild]::BitwiseAnd(0x1, $(FxCopExit))". Input string was not in a
correct format. Static method invocation should be of the form:
$([FullTypeName]::Method()), e.g. $([System.IO.Path]::Combine('a', 'b')).
I'm trying to do this:
<Warning Text="Assembly loading exception" Condition="$([MSBuild]::BitwiseAnd(0x8, $(FxCopExit))) == 0x8"/>
It's worth noting that the 0x8 on the right hand side of the condition is acceptable, so if I instead do
<Warning Text="Assembly loading exception" Condition="$([MSBuild]::BitwiseAnd(8, $(FxCopExit))) == 0x8"/>
Everything works out fine. Since the error codes I'm mapping are defined in hexadecimal, I'd much prefer to keep them in hex here as well, for future readers of the script...
As far as I can find out, it is not possible. The only way to keep the hexadecimal is to wrap it in a conversion:
<Warning Text="Assembly loading exception" Condition="$([MSBuild]::BitwiseAnd($([System.Convert]::ToInt32(`0x8`, 16)), $(FxCopExit))) == 0x8"/>
I'm not sure if this is actually better/more readable than just rewriting the number in decimal and documenting, but this is technically correct, at least...
I have run into someone else's code that declares methods like this:
- (void) method:(id)a:(NSString*)b { }
The compiler accepts this code, giving just a warning:
'a' used as the name of the previous parameter rather than as part of the selector
The code declares various functions with this type and then invokes them through NSSelectorFromString, using the signature "methodname::". So it's all consistent.
I wonder if that method signature is just a mistake or if there's more to it. Since it's used consistently in the code, I don't think this is a typo. I don't know the author so I can't tell if this is code of a genius or the opposite.
Is 'b' an anonymous parameter? (If so, shouldn't it rather be written with a blank between the "a" and ":" to indicate this better?) I can't find anything about anon parms in the ObjC docs, though.
Will there be any change in behavior if I change the syntax to giving the second parameter a name, and fixing the signature reference accordingly? I plan to make this change to get rid of the warnings, but I wonder I might create an issue that I'm not aware of.
Everything you describe is pretty much correct. It's very bad style, but technically it's just a two-argument selector which happens to have no text before the second :. I wouldn't call b an anonymous argument since you can still give it a name, it just doesn't have any descriptive text before it as part of the selector's name.
Yes, there should probably be a space after the a.
If you want to rename it, you can use Xcode's standard Refactor->Rename functionality and just insert some text before the second :. It will update all the references and you should encounter no problems.
You can use the signature method::, even though it is not recommended by most people.
Just insert a space character before each : separating the parameters, and the compiler is happy:
- (void) method:(id)a :(NSString*)b
On page 16 "Message Syntax" of The Objective-C Programming Language
this is called an "unlabeled argument", or an "argument without keyword".
Of course you can change it to
- (void) method:(id)a withB:(NSString*)b
but this changes the selector to method:withB:.
I'm trying to integrate CocoaLumberjack into a project that I inherited. I've seen it work fine in the past with other projects, but for some reason, I'm getting several errors in CocoaLumberjack's code. Examples include:
Suddenly I'm getting "Assigning to 'void *' from incompatible type 'const char [1]'" compile errors on struct properties when passing in a C string.
I'm getting warnings on C arrays of C strings saying "Conversion from string literal to 'char *' is depreciated.
"class" has suddenly become a keyword (the lowercase version)
Has anyone ever seen anything similar to this? The build settings on the project have definitely been changed a bit, but I'm not sure what was done.
Any chance you're accidentally compiling the code as C++/Obj-C++? The third point there with class becoming a keyword makes that sound plausible.
i have had this happen in vs, where the errors show up from newest to oldest as the compiler runs through the source code.Try to if your doing something like this always remember to trace to the first error and go from there. I have had some pretty crazy results by putting a semicolon (;) after an include statment
ie
<string>;
<vector>;
will throw a crazy set of errors if it is in the wrong place.
In my language I can use a class variable in my method when the definition appears below the method. It can also call methods below my method and etc. There are no 'headers'. Take this C# example.
class A
{
public void callMethods() { print(); B b; b.notYetSeen();
public void print() { Console.Write("v = {0}", v); }
int v=9;
}
class B
{
public void notYetSeen() { Console.Write("notYetSeen()\n"); }
}
How should I compile that? what i was thinking is:
pass1: convert everything to an AST
pass2: go through all classes and build a list of define classes/variable/etc
pass3: go through code and check if there's any errors such as undefined variable, wrong use etc and create my output
But it seems like for this to work I have to do pass 1 and 2 for ALL files before doing pass3. Also it feels like a lot of work to do until I find a syntax error (other than the obvious that can be done at parse time such as forgetting to close a brace or writing 0xLETTERS instead of a hex value). My gut says there is some other way.
Note: I am using bison/flex to generate my compiler.
My understanding of languages that handle forward references is that they typically just use the first pass to build a list of valid names. Something along the lines of just putting an entry in a table (without filling out the definition) so you have something to point to later when you do your real pass to generate the definitions.
If you try to actually build full definitions as you go, you would end up having to rescan repatedly, each time saving any references to undefined things until the next pass. Even that would fail if there are circular references.
I would go through on pass one and collect all of your class/method/field names and types, ignoring the method bodies. Then in pass two check the method bodies only.
I don't know that there can be any other way than traversing all the files in the source.
I think that you can get it down to two passes - on the first pass, build the AST and whenever you find a variable name, add it to a list that contains that blocks' symbols (it would probably be useful to add that list to the corresponding scope in the tree). Step two is to linearly traverse the tree and make sure that each symbol used references a symbol in that scope or a scope above it.
My description is oversimplified but the basic answer is -- lookahead requires at least two passes.
The usual approach is to save B as "unknown". It's probably some kind of type (because of the place where you encountered it). So you can just reserve the memory (a pointer) for it even though you have no idea what it really is.
For the method call, you can't do much. In a dynamic language, you'd just save the name of the method somewhere and check whether it exists at runtime. In a static language, you can save it in under "unknown methods" somewhere in your compiler along with the unknown type B. Since method calls eventually translate to a memory address, you can again reserve the memory.
Then, when you encounter B and the method, you can clear up your unknowns. Since you know a bit about them, you can say whether they behave like they should or if the first usage is now a syntax error.
So you don't have to read all files twice but it surely makes things more simple.
Alternatively, you can generate these header files as you encounter the sources and save them somewhere where you can find them again. This way, you can speed up the compilation (since you won't have to consider unchanged files in the next compilation run).
Lastly, if you write a new language, you shouldn't use bison and flex anymore. There are much better tools by now. ANTLR, for example, can produce a parser that can recover after an error, so you can still parse the whole file. Or check this Wikipedia article for more options.