Relax Void * отливка в C ++
-
27-09-2019 - |
Вопрос
В 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 *.
емкость
Марио