Stack Exchange
Копирование SAFEARRAY в вектор
Есть SAFEARRAY. Мне нужно все его элементы поместить в вектор определенного типа.
Что сделал:
SAFEARRAY * arr;
void * data;
SafeArrayAccessData(this->arr, &this->data);

template<typename T> HRESULT CVarArrayHelper::FillVector(std::vector<T> & vect) const {
    VARTYPE type;
    OLE_CHECK(SafeArrayGetVartype(this->arr, &type));
    switch (type) {
        case VT_I1:
            CreateVector<int8_t, T>(vect);
            break;
        case VT_I2:
            CreateVector<int16_t, T>(vect);
            break;
        ..............
        case VT_UI1:
            CreateVector<uint8_t, T>(vect);
            break;
        ..............
        case VT_R8:
            CreateVector<double, T>(vect);
            break;
        default:
            return E_INVALIDARG;
    }
    return S_OK;
}

template<typename T, typename R>
void CVarArrayHelper::CreateVector(std::vector<R> & vect) const {
    const T * data = static_cast<const T *>(this->data);
    if (this->len != 0) {
        vect.reserve(vect.size() + this->len);
        for (LONG i = 0; i < this->len; i++) {
            vect.push_back(static_cast<R>(*data));
            data++;
        }
    }
}

Все работает для перечисленных типов. Но мне нужно еще добавить тип VT_VARIANT. Думал решить проблему с частичной специализацией шаблона
template<typename T, typename R>
R CVarArrayHelper::GetValue(const T & data) const {
    return static_cast<R>(data);
}

template<typename R>
R CVarArrayHelper::GetValue<VARIANT>(const VARIANT & data) const {
    // Здесь каст варианта к нужному типу
}

template<typename T, typename R>
void CVarArrayHelper::CreateVector(std::vector<R> & vect) const {
    const T * data = static_cast<const T *>(this->data);
    if (this->len != 0) {
        vect.reserve(vect.size() + this->len);
        for (LONG i = 0; i < this->len; i++) {
            vect.push_back(GetValue<R>(*data));
            data++;
        }
    }
}

Но частичная специализация шаблона для методов не работает. Сейчас есть идея продублировать метод CreateVector для VARIANT
template<typename R>
void CVarArrayHelper::CreateVectorVar(std::vector<R> & vect) const {
    const VARIANT * data = static_cast<const VARIANT *>(this->data);
    if (this->len != 0) {
        vect.reserve(vect.size() + this->len);
        for (LONG i = 0; i < this->len; i++) {
            vect.push_back(GetValueVar<R>(*data));
            data++;
        }
    }
}

Ну и вызов
case VT_VARIANT:
    CreateVectorVar<T>(vect);
    break;

но не хочется дублировать код.
Что-то можно придумать?
Update
Была такая идея
template<typename T, typename R>
R CVarArrayHelper::GetValue(const T & data) const {
    if constexpr (std::is_same_v<T, VARIANT>)
        return GetValueVar<R>(data);
    else
        return static_cast<R>(data);
}

template<typename R>
R CVarArrayHelper::GetValueVar(const VARIANT & data) const {
    //
}

Но на строке return GetValueVar<R>(data); получаю ошибки компиляции

error C2440: 'initializing': cannot convert from 'const T' to 'const VARIANT &'
with
[
T=int8_t
]

Т.е. компилятор пытается скомпилировать вызов GetValueVar для всех типов. Но вроде же для if constexpr такого происходить не должно?

Задача решена. Вот так работает замечательно
template<typename T, typename R>
R CVarArrayHelper::GetValue(const T & data) const {
    if constexpr (std::is_same_v<T, VARIANT>)
        return GetValueVar<R>(data);
    else
        return static_cast<R>(data);
}

template<typename R>
R CVarArrayHelper::GetValueVar(const VARIANT & data) const {
    //
}

Только нужно было поменять версию стандарта с 14 на 17
