Monday, March 28, 2011

VA или ...

Была когда-то у меня задача связанная с VA. Был некий макрос:

#define del( pBuf ) del_impl( ( pBuf ), __FILE____LINE____FUNCTION__ )

детали del_impl не важны, но внутри в конце концов вызывался оператор delete. Потом я захотел модифицировать макрос, чтобы если передается опционально второй параметр – то внутри вызывался бы delete[]. С макросами это не так просто было сделать сразу. Порисёчив в инете я тогда придумал некое решение, но мне кажется что есть лучше. Вот то что тогда вышло (пример проверил в студии):

#include < stdarg.h >
#include < iostream >

#define SENTINEL -32768
template < class T >
inline void del_impl(
    T* &pBuf,
    const char*  szFile,
    unsigned int nLine,
    const char*  szFunc,
    unsigned int nCount,
    ...
    )
{
    va_list args;
    va_start(argsnCount);

    // bla bla bla...

    SENTINEL == va_arg( argsint ) ? delete pBuf : delete[] pBuf;

    pBuf = NULL;
    va_end(args);
}

#ifdef _MSC_VER
#   define del( pBuf, ... ) \
        del_impl( ( pBuf ), __FILE____LINE____FUNCTION__, \
            1, __VA_ARGS__SENTINEL )
#else
#   define del( pBuf, ... ) \
        del_impl( ( pBuf), __FILE__, __LINE__, __FUNCTION__, \
            1, ##__VA_ARGS__, SENTINEL )
#endif // _MSC_VER

class CTest
{
public:
    ~CTest( )
    {
        static int i = 0;
        std::cout << __FUNCTION__ << ++i << std::endl;
    }
};

int _tmain( int argc_TCHARargv[] )
{
    CTestp  new CTest;
    del( p );

    CTestpp = new CTest[10];
    del( pptrue );
    // del( pp ) // WRONG!
    //    in this case, in debug we will have an assert:
    //   _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)); from 'dbgdel.cpp'

    return 0;
}

В общем если есть более красивое или правильнее или вообще другое решение – было бы прикольно его увидеть.

No comments:

Post a Comment