Can you help me avoid this warning: 'kFontFromFontSize' macro redefined
in Gameconfig.h
#ifndef __GAME_CONFIG_H
#define __GAME_CONFIG_H
//
// Supported Autorotations:
// None,
// UIViewController,
// CCDirector
//
#define kFontFromiPaoneToiPad 2.1
#define kFontFromFontSize 2*kFontFromiPaoneToiPad
Your defines seems to work fine when I test using Visual Studio. Are you sure you are not defining these some other place as well? Perhaps your compiler treats it differently. In that case, you can use const globals instead:
const float kFontFromiPaoneToiPad = 2.1;
const float kFontFromFontSize = 2 * kFontFromiPaoneToiPad;
BTW, it is considered a good practice to use parenthesis around compound expressions in #define to avoid any potential problems when it is substituted in your code.
Related
Why do I get a compiler error when using a ternary operator in the assignment of a CGSize const like this?
CGSize const ksizeSmall = SOME_BOOLEAN_VARIABLE ? {187, 187} : {206, 206};
it does work like this...
CGSize const ksizeSmall = {187, 187};
however, I want to add a boolean expression to evaluate whether I should use one size vs. the other size. I don't want to use if / else because I have a long list of CGSize to set specifically for different purposes.
{187, 187} and {206, 206} aggregates are valid as an initialization expressions, but not as a general-purpose expressions*. That is why a ternary operator does not allow it.
If you are making an initializer for a local constant, you could use CGSizeMake:
CGSize const ksizeSmall = SOME_BOOLEAN_VARIABLE ? CGSizeMake(187, 187) : CGSizeMake(206, 206);
If SOME_BOOLEAN_VARIABLE is a compile-time constant expression, you could use conditional compilation instead:
#if SOME_BOOLEAN_VARIABLE
CGSize const ksizeSmall = {187, 187};
#else
CGSize const ksizeSmall = {206, 206};
#endif
* gcc compiler has a C language extension that offers a special syntax for doing this. It was available in Objective-C as well. However, this extension is not part of the language.
I'm trying to solve Can Xcode tell me if I forget to include a category implementation in my target?, and I came up with the following solution:
NSObject+Foo.h
extern int volatile canary;
void canaryCage() {
canary = 0;
}
NSObject+Foo.m
int canary = 0;
Now, if I #import "NSObject+Foo.h" in a source file, I'll get a linker error if that NSObject+Foo.m wasn't also included in my target.
However, every time I #import "NSObject+Foo.h" I generate a duplicate _canaryCage symbol. I can't use __COUNTER__ because I only #import "NSObject+Foo.h" in implementation files. I need canaryCage to be unique across my whole symbol table.
I need something like:
#define CONCAT(x, y) x##y
#define CONCAT2(x, y) CONCAT(x, y)
extern int volatile canary;
void CONCAT2(canaryCage, __RANDOM__)() {
canary = 0;
}
This way, if I have source files like:
Bar.m
#import "NSObject+Foo.h"
Baz.m
#import "NSObject+Foo.h"
I'll get symbols like _canaryCage9572098740753234521 and _canaryCage549569815492345, which won't conflict. I also don't want to enable --allow-multiple-definition in ld because I want other duplicate symbol definitions to cause an error. I don't want to use canaryCage for anything but a marker that I forgot to link a source file whose header I #imported.
If you make it static, each translation unit will get its own copy, and everything else should work the way you want it to - no preprocessor gymnastics required.
static void canaryCage()
{
canary = 0;
}
This answer was close, but it resulted in canaryCage being optimized away because it was dead code.
Solution:
NSObject+Foo.h
extern int canary;
__attribute__((constructor)) static void canaryCage() {
canary = 0;
}
NSObject+Foo.m
int canary = 0;
Unfortunately, this adds some overhead every time the category is imported, but the overhead is very minimal. If anyone knows a way to prevent canaryCage from being stripped, I'll happily mark their answer as correct.
I've been wondering if there's an elegant way to derive a string from an enum in Objective-C or vanilla C. I'm currently using a switch statement like so:
switch (self.requestType)
{
case MSListRequest:
serverRequestType = #"List";
break;
case MSDetailsRequest:
serverRequestType = #"Details";
break;
case MSPurchaseRequest:
serverRequestType = #"PurchaseVolume";
break;
}
I'm curious if there's a cleaner way to derive strings than this.
-edit:
I'm also using the same enum elsewhere to interface to a different system that needs to map the same enums to a different set of strings.
There's no real nice way to do this. A very simple way is to create an array:
NSString *const ENUM_NAMES[] = {
#"List", #"Details", #"PurchaseVolume", ...
};
There are alternatives that use macros and some simple preprocessor hacks to define both the names and the enum itself from the same source. However, the resulting code is more difficult to read.
// some_enum.def
X(List),
X(Details),
X(PurchaseVolume)
// some_enum.h
enum {
#define X(x) x
#include "some_enum.def"
#undef X
};
// some_enum.c
char const *const ENUM_STRING[] = {
#define X(x) #x
#include "some_enum.def"
#undef X
};
I'm not sure of the best way to generate an NSString from the preprocessor, whether you can just stick an # in it or if it's better to use (NSString *)CFSTR(x).
When I need a bunch of code like this, I write a Python script to generate the code from a text file -- it generates GPerf output for converting strings to enum, and it generates the code for converting enum to string as well. Plain old C doesn't do reflection.
I use this code to set my constants
// Constants.h
extern NSInteger const KNameIndex;
// Constants.m
NSInteger const KNameIndex = 0;
And in a switch statement within a file that imports the Constant.h file I have this:
switch (self.sectionFromParentTable) {
case KNameIndex:
self.types = self.facilityTypes;
break;
...
I get error at compile that read this: "error:case label does not reduce to an integer constant"
Any ideas what might be messed up?
For C/C++ and Objective-C must the case statement have fixed values - "reduced to an integer (read value)" at compile time
Your constants is not a real "constant" because it is a variable and I imagine it can be changed through a pointer - ie &KNameIndex
Usually one defines constants as enum
enum {
KNameIndex = 0,
kAnotherConstant = 42
};
If you would use C++, or Objective-C++ (with .mm as file extension) you could use a const statement as
const int KNameIndex = 0;
You can use
#define KNameIndex 0
...
switch (self.sectionFromParentTable) {
case KNameIndex:
self.types = self.facilityTypes;
break;
...
and it should work.
Just had the same problem and I decided to go with #define rather than enum. Works for me™ ;-)
This is a stab in the dark because I haven't used Cocoa / ObjC in a long time now, but is the member variable sectionFromParentTable not of int type?
I have not worked with Objective C, but I'd try chucking the 'extern'. At least if this were C++, the Constants.m file would not be part of the compilation unit of Other.m, so the value of KNameIndex would be unknown to the compiler. Which would explain the error; an unknowable value can't be a constant.
Does putting the definition, not just the declaration, in the Constants.h file help?
I think you are stuck with using a const int instead of a const NSInteger as switch only works with built in integral types. (not sure about your syntax with const flipped around after the type).
Take a look at the related question: Objective-C switch using objects?
The offsetof macro seems not to work under C++/CLI.
This works fine in unmanaged C++, but throws "error C2275: 'Entity' :illegal use of this type as an expression" error in CLI.
struct Property{
char* label;
PropertyTypes type;
unsigned int member_offset;
unsigned int position;
unsigned char bit_offset;
};
struct Entity{
...
bool transparent;
...
};
Property property = {"Transparent",
TYPE_BOOL,
offsetof(Entity, transparent),
0,
0}; // C2275 HERE
Does CLI have some replacement?
My guess would be that the compiler message boils down to: "offsetof" is not a known macro and if it was a function its parameters must not contain a typename.
Edit: As somebody pointed out in the comments, offsetof is actually part of the std lib. So what's missing is probably just
#include <cstddef>
Alternatively, you can use this macro implementation (taken from Win32/MFC headers):
#ifdef _WIN64
#define OFFSET_OF( s, m )\
(size_t)((ptrdiff_t)&reinterpret_cast<const volatile char&>((((s*)0)->m)) )
#else
#define OFFSET_OF( s, m )\
(size_t)&reinterpret_cast<const volatile char&>((((s*)0)->m))
#endif
Standard C++ already has an alternative; &Entity::transparent. You'll probably want to use templates when redesigning the Propery class. The type of a pointer-to-member is non-trivial.
You will need to provide the type of the object you are assigning to. Looks like there is some type-mismatch for the member in question.
See this for sample usage.
Just a shot in the dark and without a chance to double-check this - should
offsetof(Entity, transparent),
perhaps rather read
offsetof( struct Entity, transparent ),
???