Obj-C ++:用于识别Objective-C类的模板元函数?

时间:2023-01-12 17:01:27

Using Objective-C++, can I write a C++ IsObjectiveCClass<T> template metafunction such that IsObjectiveCClass<T>::value is true if and only if T is an Objective-C class?

使用Objective-C ++,我可以编写一个C ++ IsObjectiveCClass 模板元函数,当且仅当T是Objective-C类时,IsObjectiveCClass :: value才为真吗?

Exactly what are ObjC classes from the viewpoint of the C / C++ subset of the language? When used in a C / C++ context, MyClass* pointers seem to behave like ordinary C pointers; does that mean that MyClass is also a C type?

从语言的C / C ++子集的角度来看究竟是什么是ObjC类?当在C / C ++上下文中使用时,MyClass *指针似乎表现得像普通的C指针;这是否意味着MyClass也是C类型?

5 个解决方案

#1


6  

Here is a simplistic solution that should work in most (if not all? Can anyone think of when this might fail?) cases (it uses clang 3.0 via xcode 4.2 - use typedefs instead of using aliases for earlier clang versions):

这是一个简单的解决方案,应该适用于大多数(如果不是全部?有人能想到这可能会失败吗?)的情况(它使用clang 3.0通过xcode 4.2 - 使用typedef而不是使用别名用于早期的clang版本):

template<class T> struct IsObjectiveCClass 
{ 
  using yesT = char (&)[10];
  using noT = char (&)[1];
  static yesT choose(id);
  static noT choose(...);
  static T make();
  enum { value = sizeof(choose(make())) == sizeof(yesT) }; 

};

#2


5  

You can read my most recent rant about ObjC++ in this question. Avoid it as much as you can possibly get away with. Definitely don't try to integrate Objective-C into C++ template metaprogramming. The compiler might actually rip a hole in space.

你可以在这个问题上阅读我最近关于ObjC ++的咆哮。避免它尽可能地逃避。绝对不要尝试将Objective-C集成到C ++模板元编程中。编译器实际上可能会破坏空间中的一个洞。

Hyperbole aside, what you're trying to do is likely impossible. Objective-C classes are just structs. (C++ classes actually just structs too.) There's not much compile-time introspection available.

除了夸张之外,你想要做的事情可能是不可能的。 Objective-C类只是结构。 (C ++类实际上也是结构化的。)没有太多的编译时内省可用。

An id is a C pointer to a struct objc_object. At runtime, every object is an id, no matter its class.

id是指向struct objc_object的C指针。在运行时,每个对象都是一个id,无论它是什么类。

typedef struct objc_class *Class;
typedef struct objc_object {
    Class isa;
} *id;

#3


1  

As with the accepted answer, you can test whether the type is convertible to id, in C++17:

与接受的答案一样,您可以在C ++ 17中测试类型是否可以转换为id:

template <typename T>
struct is_objc_ptr : std::integral_constant<bool, 
  std::is_convertible_v<T, id> && !std::is_null_pointer_v<T>> {};
template <typename T>
constexpr bool is_objc_ptr_v = is_objc_ptr<T>::value;

Testing:

static_assert(!is_objc_ptr_v<nullptr_t>);
static_assert(!is_objc_ptr_v<int>);
static_assert(!is_objc_ptr_v<char *>);
static_assert(is_objc_ptr_v<id>);
static_assert(is_objc_ptr_v<NSObject *>);

I don't know of a way to discover ObjC inheritance relationships at compile-time; in theory they're changeable at runtime so you would have to query the runtime.

我不知道在编译时发现ObjC继承关系的方法;从理论上讲,它们在运行时是可更改的,因此您必须查询运行时。

#4


0  

I would create a template specialisation for 'id' and 'NSObject*', but you'll always be working against the language because the ObjC type system is not the C++ type system.

我会为'id'和'NSObject *'创建一个模板特化,但是你总是会对该语言起作用,因为ObjC类型系统不是C ++类型系统。

#5


0  

If you look at the implementation of the C++ STL library in Xcode, you can follow the template specialization models of others like std::is_integral or std::is_floating_point:

如果你看一下Xcode中C ++ STL库的实现,你可以遵循std :: is_integral或std :: is_floating_point之类的其他模板特化模型:

template <class T> struct isObjcObject     : public std::false_type { };
template <>        struct isObjcObject<id> : public std::true_type { };

where std::false_type and std::true_type are defined in the <type_traits> header file.

其中std :: false_type和std :: true_type在 头文件中定义。

If for whatever reason you don't have std::false_type and std::true_type (depending on your C++ version), you can define them yourself as such:

如果由于某种原因你没有std :: false_type和std :: true_type(取决于你的C ++版本),你可以自己定义它们:

template<bool B>   struct boolean_constant { static constexpr const bool value = B; };

template <class T> struct isObjcObject     : public boolean_constant<false> { };
template <>        struct isObjcObject<id> : public boolean_constant<true> { };

Note that you can also do this for Objective-C classes too:

请注意,您也可以为Objective-C类执行此操作:

template <class T> struct isObjcClass        : public std::false_type { };
template <>        struct isObjcClass<Class> : public std::true_type { };

#1


6  

Here is a simplistic solution that should work in most (if not all? Can anyone think of when this might fail?) cases (it uses clang 3.0 via xcode 4.2 - use typedefs instead of using aliases for earlier clang versions):

这是一个简单的解决方案,应该适用于大多数(如果不是全部?有人能想到这可能会失败吗?)的情况(它使用clang 3.0通过xcode 4.2 - 使用typedef而不是使用别名用于早期的clang版本):

template<class T> struct IsObjectiveCClass 
{ 
  using yesT = char (&)[10];
  using noT = char (&)[1];
  static yesT choose(id);
  static noT choose(...);
  static T make();
  enum { value = sizeof(choose(make())) == sizeof(yesT) }; 

};

#2


5  

You can read my most recent rant about ObjC++ in this question. Avoid it as much as you can possibly get away with. Definitely don't try to integrate Objective-C into C++ template metaprogramming. The compiler might actually rip a hole in space.

你可以在这个问题上阅读我最近关于ObjC ++的咆哮。避免它尽可能地逃避。绝对不要尝试将Objective-C集成到C ++模板元编程中。编译器实际上可能会破坏空间中的一个洞。

Hyperbole aside, what you're trying to do is likely impossible. Objective-C classes are just structs. (C++ classes actually just structs too.) There's not much compile-time introspection available.

除了夸张之外,你想要做的事情可能是不可能的。 Objective-C类只是结构。 (C ++类实际上也是结构化的。)没有太多的编译时内省可用。

An id is a C pointer to a struct objc_object. At runtime, every object is an id, no matter its class.

id是指向struct objc_object的C指针。在运行时,每个对象都是一个id,无论它是什么类。

typedef struct objc_class *Class;
typedef struct objc_object {
    Class isa;
} *id;

#3


1  

As with the accepted answer, you can test whether the type is convertible to id, in C++17:

与接受的答案一样,您可以在C ++ 17中测试类型是否可以转换为id:

template <typename T>
struct is_objc_ptr : std::integral_constant<bool, 
  std::is_convertible_v<T, id> && !std::is_null_pointer_v<T>> {};
template <typename T>
constexpr bool is_objc_ptr_v = is_objc_ptr<T>::value;

Testing:

static_assert(!is_objc_ptr_v<nullptr_t>);
static_assert(!is_objc_ptr_v<int>);
static_assert(!is_objc_ptr_v<char *>);
static_assert(is_objc_ptr_v<id>);
static_assert(is_objc_ptr_v<NSObject *>);

I don't know of a way to discover ObjC inheritance relationships at compile-time; in theory they're changeable at runtime so you would have to query the runtime.

我不知道在编译时发现ObjC继承关系的方法;从理论上讲,它们在运行时是可更改的,因此您必须查询运行时。

#4


0  

I would create a template specialisation for 'id' and 'NSObject*', but you'll always be working against the language because the ObjC type system is not the C++ type system.

我会为'id'和'NSObject *'创建一个模板特化,但是你总是会对该语言起作用,因为ObjC类型系统不是C ++类型系统。

#5


0  

If you look at the implementation of the C++ STL library in Xcode, you can follow the template specialization models of others like std::is_integral or std::is_floating_point:

如果你看一下Xcode中C ++ STL库的实现,你可以遵循std :: is_integral或std :: is_floating_point之类的其他模板特化模型:

template <class T> struct isObjcObject     : public std::false_type { };
template <>        struct isObjcObject<id> : public std::true_type { };

where std::false_type and std::true_type are defined in the <type_traits> header file.

其中std :: false_type和std :: true_type在 头文件中定义。

If for whatever reason you don't have std::false_type and std::true_type (depending on your C++ version), you can define them yourself as such:

如果由于某种原因你没有std :: false_type和std :: true_type(取决于你的C ++版本),你可以自己定义它们:

template<bool B>   struct boolean_constant { static constexpr const bool value = B; };

template <class T> struct isObjcObject     : public boolean_constant<false> { };
template <>        struct isObjcObject<id> : public boolean_constant<true> { };

Note that you can also do this for Objective-C classes too:

请注意,您也可以为Objective-C类执行此操作:

template <class T> struct isObjcClass        : public std::false_type { };
template <>        struct isObjcClass<Class> : public std::true_type { };