2016-06-30 8 views
3

Ich möchte ein C/C++ - Makro für null sicheren Zeiger Zugriff schreiben. Im Moment habe ich diese, die gut funktioniert:C/C++ - Makro für null sicheren Zeiger Zugriff

#define NULL_SAFE(p, e) if (p) p->e 
NULL_SAFE(myPtr, myMethod(myArg)); 

Aber was ich wirklich will, ist, so etwas haben:

NULL_SAFE(
    myPtr, myMethod(myArg), 
    myOtherPtr, myOtherMethod(myOtherArg), 
    yetAnotherMyPtr, plsStopMethod(grArg), 
    ... 
); 

, die erweitern würde:

if (myPtr) myPtr->myMethod(myArg); 
    if (myOtherPtr) myOtherPtr->myOtherMethod(myOtherArg); 
    if (yetAnotherMyPtr) yetAnotherMyPtr->plsStopMethod(grArg); 

ich denken kann, von einer ganzen Reihe von diesen möchte ich vielleicht verwenden, aber sie arbeiten alle nach dem gleichen Konzept wie dieses.

Ist das möglich? Gibt es das schon irgendwo? Irgendwelche Vorschläge? Danke für Ihre Hilfe!

+0

Wahrscheinlich besser, eine Referenz zu verwenden, so dass nichts von dieser verrückten Idee an erster Stelle erforderlich ist – paulm

+0

Werfen Sie einen Blick auf diese: http://saadahmad.ca/cc-preprocessor-metaprogramming-basic-pattern-matching-macros- und-conditionals/ – lorro

+3

Verwenden Sie C oder C++? Wenn Sie C++ verwenden, können Sie Smartpointer verwenden. – NathanOliver

Antwort

5

Wenn die NULL-Prüfung Teil eines Algorithmus ist, geben Sie einfach die NULL-Prüfung explizit ohne irgendwelche icky-Makros ein.

Wenn die NULL-Prüfung eine defensive Programmierung ist, ist die korrekte Vorgehensweise assert(ptr);. Wenn das Assert immer ausgelöst wird, beheben Sie den Fehler, der es verursacht hat. Wiederholen Sie diesen Vorgang, bis keine Fehler mehr vorhanden sind, und entfernen Sie dann die Bestätigung aus dem Produktionsqualitätscode.

+0

Es sei denn, ein Nullzeiger ist ein akzeptabler Zustand des Programms. Siehe meine Antwort auf CodyGrays Kommentar. Danke für Ihren Vorschlag! – RoboCop87

1

Das nächste, was ich dazu bekommen kann, ist mit C++ 11 Variadic Vorlagen und C99 Variadic Makros ... Entschuldigung, wenn Ihre Plattform es nicht erlaubt, egal, es war viel Spaß, mit dem Code zu kommen!

#include <functional> 
#include <iostream> 

template<class T> 
void stuff(T a) 
{ 
    std::cout<< "stuff:" << a << std::endl; 
} 

template<class T> 
void other_stuff(T a) 
{ 
    std::cout<< "other_stuff:" << a << std::endl; 
} 

template <typename Test, typename ToCall> 
void tester(Test t, ToCall tc) 
{ 
    if(t) tc(); 
} 

template <typename Test, typename ToCall, typename... Others> 
void tester(Test t, ToCall tc, Others... args) 
{ 
    if(t) tc(); 
    tester(args...); 
} 

#define FUN_WRAP(a,b) std::bind(a<decltype(b)>, (b)) 
#define NULL_SAFE(...) tester(__VA_ARGS__) 

int main() 
{ 
    NULL_SAFE(1, FUN_WRAP(stuff, 1), 
     0, FUN_WRAP(stuff, 2), 
     1, FUN_WRAP(other_stuff, 3) 
     ); 
} 
+0

Das sieht gut aus, aber brauchen Sie sogar das NULL_SAFE-Makro, sobald Sie die variable Template-Funktion haben? Auch ich war auf der Suche nach einem Makro, so dass es für pre C++ 11 Compiler und C zurück portierbar war, aber das wäre gut, wenn sich herausstellt, dass eine reine Makro-Lösung nicht möglich ist! – RoboCop87

+1

@ RoboCop87: Eine reine Makrolösung ist möglich. Aber es ist zu eklig, ernsthaft nachzudenken. –

+0

Nein, Sie brauchen das 'NULL_SAFE' Makro nicht wirklich. – fritzone

3

C++ 11:

inline void null_safe() 
{ 
} 

template <typename Ptr, typename Fn, typename... Args> 
void null_safe(Ptr&& ptr, Fn&& fn, Args&&... args) 
{ 
    if (ptr) 
     fn(); 
    // you could put "else" here                            
    null_safe(std::forward<Args>(args)...); 
} 

Sie alle abrufbaren als zweites Argument verwenden können, so:

int f2() { 
    return printf("f2\n"); 
} 

int f3() { 
    return printf("f3\n"); 
} 

int main() 
{ 
    int i1 = 1; 

    null_safe(
     &i1, f2 
     ); 

    null_safe(
     NULL, f2, 
     &i1, f3 
     ); 
} 

Sie können auch jedes Prädikat als erstes Argument verwenden.

Warum ist es NULL dort und nicht nullptr ist als Übung für den Leser übrig.

+0

Ich musste das googeln. nullptr berechnet einen Zeigertyp vs. NULL, der eine Ganzzahl auswertet, die für das Funktionieren Ihrer Vorlage benötigt wird. Danke für die Übung! – RoboCop87

+0

Wenn Sie die Vorlage Straße gehen, übergeben Sie möglicherweise Argumente an die Funktionen ... –