确定指针在运行时是否指向C++类或Objective-C类是否可能?

5

问题在主题中。

我想编写一些通用的模板函数来安全地删除对象,并且想知道是否可以使用类似以下方式的内容:

template< class T > void SafeDelete( T*& pVal )
{
    if(objc_is_cpp_object(pVal)){
        delete pVal;
        pVal = NULL;
    }
    else
        [pVal release]
}

1
为什么你想在不同的语言下使用相同的函数名称?为什么不能通过使用不同的名称来区分它们呢? - iammilind
2
C++дёӯзҡ„deleteе’ҢObj-Cдёӯзҡ„releaseж„Ҹд№үе®Ңе…ЁдёҚеҗҢпјӣж··ж·ҶиҝҷдёӨиҖ…дјјд№ҺжҳҜдёҖдёӘеҸҜз–‘зҡ„жғіжі•гҖӮ - David Gelhar
我先考虑了不同的名称,然后突然好奇起来,是否可能针对两种语言提出相同的问题。然后我想,尽管这可能不是一个很好的主意,但仍然感到好奇 :-) 所以这主要是一个理论性的问题。 - andrey.s
2个回答

4

如评论中所述,我建议不要混合使用C++的delete和Objective-C的release
从技术角度来看,您可以使用以下SFINAE技巧运行时:

template<typename T> struct void_ { typedef void type; };

template<typename, typename = void>
struct CppType { static const bool value = false; };
template<typename T>
struct CppType<T, typename void_<int (T::*)>::type> { static const bool value = true; };

template< class T > 
void SafeDelete( T*& pVal )
{
  if(CppType<T>::value || std::is_pod<T>::value) {  // <-----
    delete pVal;
    pVal = 0;
  }   
  else {
     // [pVal release];
  }   
}

可能在C++11、boost等中已经有is_pod函数可用,但实现起来也很简单。

你能解释一下 "typename void_<int (T::*)>::type" 是什么意思吗?据我所知,这个字符串在 objc 对象的情况下将被替换为 void 类型,并且模板的专门版本将返回 false;但我仍然不明白这是如何发生的。谢谢。 - andrey.s
@andrey.s,这个机制被称为SFINAE。int (T::*)表示成员变量的指针。现在,只有对于C++ classunion类型才可以使用成员指针,而不能针对其他实体。因此,如果给定的类型是C++ class类型,则 CppType<T>::value 将为 true,您可以执行C++特定任务。 - iammilind

2

Objective-C指针与C++指针相同:它们是指向内存中各种对象的4到8个字长的整数值。Objective-C编译器支持以多种格式输出值,如C、C++和Objective-C对象布局。

就这些了,实际上没有太多其他的东西。

你可以尝试做一些奇怪的事情,比如创建一个类,其中一个字段始终包含一个魔术值:

template <class T>
class Magic {
    private:
        const char magic[] = 1234567;
    public:
        bool is_object() const {
            return magic == 1234567;
        }
}

那么你可以像这样测试它:
bool is_cpp(void *ptr) {
    return ((Magic*) ptr)->is_object();
}

但需要预先警告的是,这种方法非常“hacky”。

你的建议是为所有cpp对象使用基础的"Magic"类吗? - andrey.s
这是一般的想法。再强调一下,这不是你想在生产环境中做的事情,因为没有特殊的值...... - alexgolec
Objective-C带有这个魔法:所有的Objective-C指针地址都是struct objc_object类型,其(虽然是私有的)定义惯用法必须包含一个isa_t isa成员...虽然我不知道运行时检查,但我个人发现objc_object::isa已经足够好用于SFINAE,例如objc::traits::is_object<T>;请参见:http://git.io/vCsLa - 更多阅读资料:http://unixjunkie.blogspot.de/2006/02/nil-and-nil.html以及objc运行时源代码- http://www.opensource.apple.com/source/objc4/objc4-647/runtime/objc-private.h - fish2000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接