13

Objective-C で変数がオブジェクトかプリミティブかを検出するマクロを探しています。

このコンテキストでは、パラメーターは変数でなければならず、決して式ではないことを知っています。

これが私が思いついた最高のものです:

#define IS_OBJECT(x)    ( @encode(__typeof__(x))[0] == '@' )
#define IS_PRIMITIVE(x) ( !IS_OBJECT(x) )

使用法:

NSString *testString = @"test";
NSString *nilString = nil;
NSInteger testInteger = 1;

STAssertTrue(IS_OBJECT(testString), @"IS_OBJECT(testString) must be YES");
STAssertTrue(IS_OBJECT(nilString), @"IS_OBJECT(nilString) must be YES");
STAssertFalse(IS_OBJECT(testInteger), @"IS_OBJECT(testInteger) must be NO");

もっと良い方法があるはずです。


アップデート

@ChrisDevereux のコメントを考慮して、IS_OBJECT マクロを更新しました。

#define IS_OBJECT(x) ( strchr("@#", @encode(__typeof__(x))[0]) != NULL )

合格するようになりました:

NSString *testString = @"test";
NSString *nilString = nil;
NSInteger testInteger = 1;
Class classTest = [NSString class];

STAssertTrue(IS_OBJECT(testString), @"IS_OBJECT(testString) must be YES");
STAssertTrue(IS_OBJECT(nilString), @"IS_OBJECT(nilString) must be YES");
STAssertFalse(IS_OBJECT(testInteger), @"IS_OBJECT(testInteger) must be NO");
STAssertTrue(IS_OBJECT(classTest), @"IS_OBJECT(classTest) must be YES");

私はまだこの答えが好きではありません。もっと滑らかなものがあることを願っています。ランタイム ライブラリにこれを行うものはありますか?

4

1 に答える 1

7

C11 の一般的な選択メカニズムを使用する別の方法を次に示します。_Genericは標準 (現代) C であり、しばらくの間 clang でサポートされています。

#define IS_OBJECT(T) _Generic( (T), id: YES, default: NO)

それは私にとって少しランタイムっぽい感じがしないので、@encode途中でそれを好みます。しかし、正直なところ、私はマクロが与える力が大好きで、_Genericより多くの人がマクロを使い始めるべきだと思うので、この回答に使用しました。ご存じない場合は、上記のリンクにある Robert Gamble の記事をお読みください。

于 2012-12-27T16:25:10.047 に答える