2012-03-08 8 views
5

La domanda è in argomento.È possibile determinare in fase di esecuzione i punti del puntatore alla classe C++ o alla classe Objective-C?

voglio scrivere qualche funzione Modello universale per l'eliminazione di oggetti sicuri e chiedendo è possibile usare qualcosa di simile:

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

Perché si desidera utilizzare lo stesso nome di funzione per lingue diverse? Perché non riesci a distinguerli usando un nome diverso? – iammilind

+2

C++ 'delete' e Obj-C' release' significano cose abbastanza diverse; confondere i due sembra al meglio un'idea discutibile. –

+0

Ho pensato prima a un nome diverso, poi mi sento solo curioso di sapere che è possibile avere una stessa domanda per entrambe le lingue. E poi ho pensato che potrebbe non essere un'idea molto buona, ma comunque mi sento stranamente :-) Quindi questa è una domanda per lo più teorica. –

risposta

4

Come menzionato nei commenti, suggerirei di non mescolare C++ delete e Objective-C release.
Proprio per il punto di vista tecnico, è possibile utilizzare il seguente SFINAE trucco runtime:

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

Possibilmente, is_pod è disponibile in C++ 11, aumentare ecc, ma è facile da implementare.

+0

Puoi spiegare cosa significa "typename void_ :: type"? Per quanto mi risulta l'idea è che questa stringa in caso di oggetto objc verrà sostituita dal tipo void e la versione specializzata del modello restituirà false; Ma non riesco a capire come ciò avvenga ancora. Grazie. –

+0

@ andrey.s, questo meccanismo si chiama SFINAE. 'int (T :: *)' indica il puntatore alla variabile membro. Ora, il puntatore al membro è possibile solo per 'class' o' union' in C++ e non per qualsiasi altra entità. Quindi, se un dato tipo è un tipo 'class' C++, allora' CppType :: value' sarà 'true' ed è possibile eseguire attività specifiche di C++. – iammilind

+2

Questo è davvero fantastico, grazie! –

2

puntatori Objective-C sono le stesse di puntatori C++: 4-a-8 valori interi di parole che puntano a vari oggetti in memoria. Il compilatore Objective-C supporta l'output di valori in più formati, come i layout di oggetti C, C++ e Objective-C.

Questo è tutto. Non c'è davvero molto oltre.

Si può provare a fare qualcosa di hacky come creare una classe in cui un campo contiene sempre un valore magico:

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

allora si potrebbe verificare in questo modo:

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

Ma sappiate che questo è estremamente hacky.

+0

Il tuo suggerimento utilizza la classe "Magic" di base per tutti gli oggetti cpp? –

+0

questa è l'idea generale. di nuovo, questo non è qualcosa che vuoi fare in produzione, perché nessun valore è speciale ... – Alex

+0

Objective-C viene fornito con questa magia: tutti i destinatari del puntatore all'obiettivo-c sono di tipo 'struct objc_object', la cui definizione (albiet private) idiomaticamente deve contenere un membro 'isa_t isa' ... mentre non so dell'ispezione di runtime, personalmente ho trovato' objc_object :: isa' abbastanza buono per SFINAE es. 'objc :: traits :: is_object '; vedere: http://git.io/vCsLa - Ulteriori letture: http://unixjunkie.blogspot.de/2006/02/nil-and-nil.html più la sorgente di runtime objc - http: //www.opensource. apple.com/source/objc4/objc4-647/runtime/objc-private.h – fish2000

Problemi correlati