2012-03-08 14 views
5

Pytanie dotyczy tematu.Czy można określić w czasie wykonywania wskaźnik wskazuje na klasę C++ lub na klasę Objective-C?

Chcę napisać jakąś uniwersalną funkcję szablonu dla bezpiecznych obiektów Usuwanie i zastanawiasz się, czy to możliwe, aby używać mniej więcej tak:

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

Dlaczego chcesz używać tej samej nazwy funkcji dla różnych języków? Dlaczego nie możesz ich odróżnić, używając innej nazwy? – iammilind

+2

C++ 'delete' i Obj-C' release' oznaczają całkiem różne rzeczy; łączenie tych dwóch wydaje się w najlepszym wypadku wątpliwym pomysłem. –

+0

Najpierw myślałem o innym nazwisku, a następnie z zainteresowaniem patrzę na to, że możliwe jest posiadanie tego samego pytania w obu językach. A potem pomyślałem, że to może nie być zbyt dobry pomysł, ale wciąż czuję się ciekawie :-) Więc to jest głównie teoretyczne pytanie. –

Odpowiedz

4

Jak wspomniano w komentarzach, sugerowałbym nie mieszać C++ delete i Objective-C release.
Tylko dla technicznego punktu widzenia, można użyć następującego SFINAE sztuczka Czas:

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]; 
    } 
} 

Ewentualnie is_pod jest dostępne w C++ 11, wzmocnienia itp Ale to jest łatwe do wdrożenia.

+0

Czy możesz wyjaśnić, co oznacza "typename void_ :: type"? O ile rozumiem, pomysł jest taki, że ten ciąg znaków w przypadku obiektu objekt zostanie zastąpiony pustym typem, a wyspecjalizowana wersja szablonu zwróci wartość false; Ale nie mogę zrozumieć, jak to się dzieje. Dziękuję Ci. –

+0

@ andrey.s, ten mechanizm nazywa się SFINAE. 'int (T :: *)' oznacza wskaźnik do zmiennej składowej. Teraz wskaźnik do elementu jest możliwy tylko dla C++ 'class' lub' union', a nie dla żadnej innej jednostki. Tak więc, jeśli dany typ jest typem "C++", to 'CppType :: value' będzie miał wartość" true "i można wykonywać określone zadania w C++. – iammilind

+2

To naprawdę fajne, dzięki! –

2

Objective-C wskaźniki są takie same jak C++ wskaźniki: 4-do-8 liczby całkowite ze słowem wskazujące różne obiekty w pamięci. Kompilator Objective-C obsługuje wyprowadzanie wartości w wielu formatach, takich jak układy obiektów C, C++ i Objective-C.

To wszystko. Naprawdę niewiele jest poza tym.

Można spróbować zrobić coś hacky jak utworzyć klasę gdzie pole zawsze zawiera magiczną wartość:

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

następnie można przetestować go tak:

bool is_cpp(void *ptr) { 
    return ((Magic*) ptr)->is_object(); 
} 

Ale być uprzedzony, że to jest wyjątkowo hacky.

+0

Twoja sugestia używa podstawowej klasy "Magic" dla wszystkich obiektów cpp? –

+0

to ogólna idea. znowu, nie jest to coś, co chcesz zrobić w produkcji, ponieważ żadne wartości nie są szczególne ... – Alex

+0

Objective-C ma tę magię: wszyscy adresatami wskaźnika celu są typu 'struct objc_object', których definicja (albiet private) idiomatycznie musi zawierać element 'isa_t isa' ... podczas gdy ja nie wiem o inspekcji środowiska wykonawczego, osobiście znalazłem dość" wystarczająco "dla obiektu SFINAE:" objc_object :: isa " 'objc :: traits :: is_object '; zobacz: http://git.io/vCsLa - Dalsze czytanie: http://unixjunkie.blogspot.de/2006/02/nil-and-nil.html oraz źródło runtime objc - http: //www.opensource. apple.com/source/objc4/objc4-647/runt/objc-private.h – fish2000

Powiązane problemy