Вопрос

В C, это не ошибка для литых указателей на и из void *.

Основным препятствием в портировании к C ++ является необходимость броски указателей при возврате из функций, занимающихся общими указателями, такими как malloc, и функции, объявленные в моем собственном коде, например void *block_get(Blkno const blkno);.

Мой код, однако, предназначен для компиляции C и C ++ компиляторы успешно. Если я предоставим явные каскаты везде ради C ++, они должны быть кастами в стиле C, и я могу быть замаскированными ошибками из-за литья не указателей типов в и из типов указателей с обоих языков.

Моя справочная ошибка следующая:

struct Cpfs *cpfs = calloc(1, sizeof(*cpfs));

который в MSVC производит:

Ошибка 2 Ошибка C2440: «Инициализация»: не может преобразовать из «void *» на 'CPFS *' e: src cpfs cpfs.c 179

Очевидно, я не могу использовать new или static_cast которые я буду естественным образом использовать, если бы я больше не использовал C. Какой лучший способ обеспечить максимальный тип безопасности void *Для каждого языка с минимальной пышностью?

Это было полезно?

Решение

Может быть что-то вроде этого? (непроверенный, компилятор не доступен, не использует макросы очень часто):

#ifdef __cplusplus
    #define pointer_cast(type, pointer) reinterpret_cast<type>(pointer)
#else
    #define pointer_cast(type, pointer) (type)(pointer)
#endif

Другие советы

Я бы предложил просто просто использовать Chasts Chill Chant, либо обертывающие литые в макросе, который либо не расширяется (в C), либо static_cast в C ++.

Если ваш компилятор поддерживает decltype(), вы можете использовать немного макро-магии, чтобы избежать явного повторения имени типа (и, благодаря sizeof, Размер элемента):

#ifdef __cplusplus
#define my_calloc(VAR, COUNT) \
    static_cast<decltype(VAR)>(std::calloc(COUNT, sizeof *VAR))
#else
#define my_calloc(VAR, COUNT) calloc(COUNT, sizeof *VAR)
#endif

Пример использования:

#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif

struct Cpfs *cpfs = my_calloc(cpfs, 42);

Очистительное решение, вероятно, будет просто использовать компилятор C и связать файлы объектов, хотя ...

Сделайте замену функцию распределителя, которую вы можете определить по-разному для сборки C и C ++: - что-то вроде этого в заголовом файле:

#ifdef __cplusplus
template<typename TypeT>
TypeT* MyAlloc(TypeT** pOut,size_t cb){
  *pOut = static_cast<TypeT*>(malloc(cb)); //aint c++ pretty.
  return *pOut;
}
#else
  extern void* MyAlloc(void** ppv, size_t cb);
#endif

Теперь у вас есть в C ++ сборки, функция, которая может сделать вывод типа вещей, с которыми его занимаются, а в C сборках, ее обычная функция, которая возвращает пустоту *.

Единственная проблема - это необходимость пройти в указателе на выделение - компилятор C ++ не пытается вывести параметр шаблона, основанный только на возвращенном типе функции функции AFAIK. Итак, вы могли бы назвать это агонично, как это: -

int *p;
if(MyAlloc(&p,sizeof(int)*n)){
  ...

Единственное решение, которое я знаю, это делать явную кастинг:

struct Cpfs *cpfs = (Cpfs*)calloc(1, sizeof(*cpfs));

Здесь оба компилятора удовлетворены. Также это помните, что для старых компиляторов Malloc может вернуть Char *.

емкость

Марио

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top