可以将新的Clang Objective-C文字重定向到自定义类吗?

Rab*_*bit 18 objective-c clang objective-c-literals

虽然超载@开始踏上危险的领域,但我喜欢在Clang 3.1中添加新的Objective-C文字.不幸的是,新的文字对我来说用处有限.除了代码需要与AppKit接口的情况之外,我大多放弃使用Foundation类来支持我自己的自定义框架(出于各种原因;其中大部分是我需要直接控制所使用的内存分配模式按对象).

我总是可以使用一些运行时技巧来传递新创建的对象作为我的自定义类(并且我已经与字符串对象文字有关,因为只有非Apple GCC运行时支持该-fconstantstring=class标志),但这是一个黑客充其量并抛弃我通过替换等效的基础类开始获得的所有好处.

与字符串对象文字不同,新文字Clang实现实际上不是常量类(内存布局是硬编码的); 而是将适当的消息发送到它们各自的类,以在运行时创建和初始化新对象.效果与您自己创建对象的效果没有什么不同.理论上,它意味着使用的类和新文字调用的方法不是硬编码的.在实践中我找不到任何方法来改变它们以指向我自己的自定义类和方法(实际上我只是想指向一个自定义类;在运行时将虚拟方法指向实际方法并不困难).

当我第一次看到这个时,我真的希望找到一组可以用来做我要求的标志,但是由于我没有找到任何标志,我希望有人有解决方案.

Eon*_*nil 12

您可以使用@compatibility_alias关键字技巧将类替换为某些Objective-C文字.

这是一个例子.

@compatibility_alias NSNumber AAA;
Run Code Online (Sandbox Code Playgroud)

当然,您应该为新类提供适当的实现.

#import <Foundation/NSObject.h>

@interface  AAA : NSObject
+ (id)numberWithInt:(int)num;
@end

@implementation AAA
+ (id)numberWithInt:(int)num
{
    return  @"AAAAA!!!";    // Abused type system just to check result.
}
@end

@compatibility_alias NSNumber AAA;
Run Code Online (Sandbox Code Playgroud)

现在,Clang将为您完成这项工作.我确认这适用于数字,数组,字典文字.不幸的是,字符串文字似乎是静态发出的,所以它不起作用.

有关@compatibility_alias关键字的更多信息,请参阅此处.

注意

因为@compatibility_aliaskeyword是一个适用于当前编译单元的编译器指令,所以需要将编译单元分开以避免与Apple的Foundation Kit中的NSObject类重复符号.这就是我做到的.

的main.m

#import "test.h" // Comes before Foundation Kit.
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        NSLog(@"return of test = %@", test());
        // insert code here...
        NSLog(@"Hello, World!");

    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

test.h

id test();
Run Code Online (Sandbox Code Playgroud)

test.m

#import "test.h"
#import <Foundation/NSObject.h>

@interface  
AAA : NSObject
+ (id)numberWithInt:(int)v;
+ (id)arrayWithObjects:(id*)pobj count:(int)c;
+ (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c;
@end
@implementation AAA
+ (id)numberWithInt:(int)v
{
    return  @"AAAAA as number!!!";
}
+ (id)arrayWithObjects:(id*)pobj count:(int)c
{
    return  @"AAAAA as array!!!";
}
+ (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c
{
    return  @"AAAAA as dictionary!!!";
}
@end



@compatibility_alias NSDictionary AAA;
@compatibility_alias NSArray AAA;
@compatibility_alias NSNumber AAA;



id test()
{
//  return  @{};
//  return  @[];
    return  @55;
}
Run Code Online (Sandbox Code Playgroud)

结果.

2013-03-23 08:54:42.793 return of test = AAAAA!!!
2013-03-23 08:54:42.796 Hello, World!
Run Code Online (Sandbox Code Playgroud)


Quu*_*one 11

这些评论都是正确的,但总结一下:

  • 没有.

苹果的意义@{},@[]@""文字是硬编码到锵.你可以在这里看到它:http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp?view = markup这些都是相当模块化的,这意味着它不会很难Clang黑客添加了她自己的文字语法......但"模块化"并不意味着"可以从外部访问".添加新语法甚至将现有语法重定向到新类肯定需要自己重建Clang.

这是一篇博客文章,关于NSURL通过黑客入侵其内部来为Clang 添加文字:http://www.stuartcarnie.com/2012/06/llvm-clang-hacking-part-3.html(谢谢@Josh Caswell)


如果您愿意使用带有C++ 11扩展的Objective-C++,您可以使用"用户定义的文字",这样您就可以编写类似于

NSURL *operator ""URL (const char *s) { return [NSURL URLWithString: @(s)]; }

int main() {
    ...
    NSURL *myurl = "ftp://foo"URL;
    ...
}
Run Code Online (Sandbox Code Playgroud)

Mike Ash博客的评论中提到了这一点.http://www.mikeash.com/pyblog/friday-qa-2012-06-22-objective-c-literals.html但这看起来不是很客观C-ish(或非常C++ ish!) ,它只适用于Objective-C++ 11编译器,一般情况下请不要这样做.:)