C-> C ++ Автоматически приводить пустой указатель к указателю типа в C ++ в #define, если тип не указан (стиль C) [MSVS] - PullRequest
7 голосов
/ 27 октября 2010

Привет!

Я использовал следующий макрос C , но в C ++ он не может автоматически разыграть void*на type*.

#define MALLOC_SAFE(var, size) { \
    var = malloc(size); \
    if (!var) goto error; \
}

Я знаю, я могу сделать что-то вроде этого:

#define MALLOC_SAFE_CPP(var, type, size) { \
    var = (type)malloc(size); \
    if (!var) goto error; \
}

Но я не хочу переписывать большую часть кода, где MALLOC_SAFE был использован.

Есть ли способ сделать это без указания типа для макроса?Может быть, некоторые MSVC 2005 #pragma / __declspec / другие?

ps: я не могу использовать компилятор C, потому что мой код является частью (одного из сотен модулей) большогопроект.И теперь это на C ++.Я знаю, я могу построить свой код отдельно.Но это старый код, и я просто хочу его быстро портировать.

Вопрос касается void * casting;) Если это невозможно, я просто заменю MACRO_SAFE на MACRO_SAFE_CPP

Спасибо!

Ответы [ 4 ]

33 голосов
/ 27 октября 2010

Чтобы сделать ответ Джеймса еще более грязным, если у вас нет поддержки decltype, вы также можете сделать это:

template <typename T>
class auto_cast_wrapper
{
public:
    template <typename R>
    friend auto_cast_wrapper<R> auto_cast(const R& x);

    template <typename U>
    operator U()
    {
        return static_cast<U>(mX);
    }

private:
    auto_cast_wrapper(const T& x) :
    mX(x)
    {}

    auto_cast_wrapper(const auto_cast_wrapper& other) :
    mX(other.mX)
    {}

    // non-assignable
    auto_cast_wrapper& operator=(const auto_cast_wrapper&);

    const T& mX;
};

template <typename R>
auto_cast_wrapper<R> auto_cast(const R& x)
{
    return auto_cast_wrapper<R>(x);
}

Тогда:

#define MALLOC_SAFE(var, size)                      \
{                                                   \
    var = auto_cast(malloc(size));                  \
    if (!var) goto error;                           \
}

Я расширил эту утилиту (в C ++ 11) на мой блог . Не используйте это ни для чего, кроме зла.

13 голосов
/ 27 октября 2010

Я не рекомендую делать это;это ужасный код, и если вы используете C, вы должны скомпилировать его с компилятором C (или, в Visual C ++, как файл C)

Если вы используете Visual C ++, вы можете использовать1005 *:

#define MALLOC_SAFE(var, size)                      \
{                                                   \
    var = static_cast<decltype(var)>(malloc(size)); \
    if (!var) goto error;                           \
}
5 голосов
/ 27 октября 2010

Например, вот так:

template <class T>
void malloc_safe_impl(T** p, size_t size)
{
    *p = static_cast<T*>(malloc(size));
}

#define MALLOC_SAFE(var, size) { \
    malloc_safe_impl(&var, size); \
    if (!var) goto error; \
}
1 голос
/ 27 октября 2010

Есть ли причина, по которой никто просто не приводит var , ваш аргумент к SAFE_MALOC ()?Я имею в виду, malloc () возвращает указатель.Вы храните его где-то, который принимает указатель ... Есть много всяких аккуратных типов безопасных вещей, на которые уже указывали другие люди ... Мне просто интересно, почему это не сработало:

#define MALLOC_SAFE(var,size)  {  \
    (* (void **) & (var)) = malloc(size); \
    if ( ! (var) ) goto error;    \
    }

Да ... я знаю.Он болен и выбрасывает безопасность типов прямо в окно.Но прямое ((void *) (var)) = приведение не всегда сработает.

...