Если вы не хотите использовать шаблоны и вам не нужны специализированные функции, вы можете использовать брутто-макрос , чтобы решить первую проблему, связанную с необходимостью приводить из PVOID
каждый раз, когда вы Звоните SafeArrayVariantPointer
:
Примерно так:
#define CAST_TYPE_VT_VARIANT (VARIANT *)
#define CAST_TYPE_VT_LONG (long *)
#define SAFE_ARRAY_DATA_POINTER(vData, vType, dimSize, elems1D, elems2D) \
CAST_TYPE_##vType SafeArrayDataPointer((vData), (vType), (dimSize), (elems1D), (elems2D))
Тогда вы можете позвонить, как:
VARIANT *pDataArray = SAFE_ARRAY_DATA_POINTER(vData, VT_VARIANT, 2, Elems1D, Elems2D);
Но сначала вам нужно изменить сигнатуру метода, чтобы аргумент ArrayType
принимался как long
, а не const long &
.
Обратите внимание, что предполагается, что второй параметр SAFE_ARRAY_DATA_POINTER
макрос должен быть литералом, который соответствует одному из определенных вами макросов CAST_TYPE_ *. Это не может быть переменной.
Для вас второй вопрос о избыточном параметре Junk
, вы можете создать перегруженную функцию SafeArrayDataPointer
, которая возвращает только размер первого измерения. Он может вызвать первую версию SafeArrayDataPointer
и отбросить размер второго измерения.
Что-то вроде:
PVOID SafeArrayDataPointer(VARIANT &v, long ArrayType, const long &ArrayDims, long &Elems1D)
{
long Elems2D;
PVOID *toReturn = SafeArrayDataPointer(v, ArrayType, ArrayDims, Elems1D, Elems2D);
if (Elems2D != 0) toReturn = NULL;
return toReturn;
}
Однако, чтобы решить эту проблему, я бы, вероятно, использовал шаблоны.
Во-первых, создайте набор array_type_traits
классов, которые выставляют typedef
для вашего типа приведения с длинным значением VT_LONG
, VT_VARIANT
и т. Д.
//Generic array_type_traits class
template<long array_type>
class array_type_traits
{
public:
typedef PVOID cast_type;
};
//Specialized for VT_LONG
template<>
class array_type_traits<VT_LONG>
{
public:
typedef long * cast_type;
};
//Specialized for VT_VARIANT
template<>
class array_type_traits<VT_VARIANT>
{
public:
typedef VARIANT * cast_type;
};
Продолжайте специализировать их для каждого типа VT_ *, который у вас есть.
Далее, инкапсулируйте вашу SafeArrayDataPointer
функцию внутри класса SafeArrayDataPointerBase
.
//Base class which has one static function Get() that returns a PVOID
class SafeArrayDataPointerBase
{
protected:
static PVOID Get(VARIANT& vData, long vType, long dimSize, long& elems1D, long& elems2D)
{
// Place your SafeArrayDataPointer function code here
}
};
Теперь создайте свой класс, который будет вызывать `SafeArrayDataPointerBase :: Get (), а затем приведите результат к правильному типу.
template<long ArrayType>
class SafeArrayDataPointer : public SafeArrayDataPointerBase
{
public:
typedef typename array_type_traits<ArrayType>::cast_type cast_type;
static cast_type Get(VARIANT& v, long ArrayDims, long& Elems1D, long& Elems2D)
{
return (cast_type) SafeArrayDataPointerBase::Get(v, ArrayDims, ArrayType, Elems1D, Elems2D);
}
};
И, наконец, вы бы назвали класс шаблона следующим образом:
VARIANT *vp = SafeArrayDataPointer<VT_VARIANT>::Get(v, ArrayDims, Elems1D, Elems2D);
long *vl = SafeArrayDataPointer<VT_LONG>::Get(v, ArrayDims, Elems1D, Elems2D);