这个模板函数可以适应以下方法吗?

Can this template function be adapted to account for the following method?

这个问题是这个问题的后续问题:

这是我的新模板函数:

template<typename from, typename to>
void CMSATools::ConvertSAFEARRAY(SAFEARRAY* psaItems, to& rItems)
{
    from* pVals = nullptr;
    HRESULT hr = SafeArrayAccessData(psaItems, (void**)&pVals); // direct access to SA memory

    if (SUCCEEDED(hr))
    {
        long lowerBound, upperBound;  // get array bounds
        hr = SafeArrayGetLBound(psaItems, 1, &lowerBound);
        if (FAILED(hr))
            throw _com_error(hr);

        hr = SafeArrayGetUBound(psaItems, 1, &upperBound);
        if (FAILED(hr))
            throw _com_error(hr);

        rItems.clear();
        long cnt_elements = upperBound - lowerBound + 1;
        for (int i = 0; i < cnt_elements; ++i)  // iterate through returned values
        {
            rItems.push_back(pVals[i]);
        }
        hr = SafeArrayUnaccessData(psaItems);
        if (FAILED(hr))
            throw _com_error(hr);
    }
    else
    {
        throw _com_error(hr);
    }

    hr = SafeArrayDestroy(psaItems);
    if (FAILED(hr))
        throw _com_error(hr);
}

我有另一个方法,我希望能够与上面的模板函数一起使用:

void CMSATools::ConvertSAFEARRAY_BSTR(SAFEARRAY* psaStrings, CStringArray& rAryStrings)
{
    BSTR *pVals = nullptr;
    HRESULT hr = SafeArrayAccessData(psaStrings, (void**)&pVals); // direct access to SA memory

    if (SUCCEEDED(hr))
    {
        long lowerBound, upperBound;  // get array bounds
        hr = SafeArrayGetLBound(psaStrings, 1, &lowerBound);
        if (FAILED(hr))
            throw _com_error(hr);

        hr = SafeArrayGetUBound(psaStrings, 1, &upperBound);
        if(FAILED(hr))
            throw _com_error(hr);

        rAryStrings.RemoveAll();
        long cnt_elements = upperBound - lowerBound + 1;
        for (int i = 0; i < cnt_elements; ++i)  // iterate through returned values
        {
            CString strPublisher(pVals[i]);

            rAryStrings.Add(strPublisher);
        }
        hr = SafeArrayUnaccessData(psaStrings);
        if (FAILED(hr))
            throw _com_error(hr);
    }
    else
    {
        throw _com_error(hr);
    }

    hr = SafeArrayDestroy(psaStrings);
    if (FAILED(hr))
        throw _com_error(hr);
}

问题是所有其他参数都来自 std::list 而我们使用 push_back。在这种情况下,当它是 CStringArray 类型时,我需要使用 Add(...) (并且还首先创建 CString 元素)。

我看到很多建议 here 但我不清楚最简单的方法应该是什么。


看来我应该能够:std::is_same<from,CStringArray>::value 看看它们是否相同,但答案似乎不赞成使用这种方法。

在这种情况下,并发症是 clearpush_back 调用 CStringArray 没有实现。虽然两者都可以像 Templated check for the existence of a class member function? 中描述的那样一般地解决,但是更简单的方法可以通过使用几个辅助函数模板来覆盖所提出的案例。

// default implementations for <T, std::list<T>>
template<typename to>
void to_clear(to &rItems)
{   rItems.clear(); }

template<typename from, typename to>
void to_push_back(const from &rItem, to &rItems)
{   rItems.push_back(rItem); }

// specializations for <BSTR, CStringArray>
template<>
void to_clear(CStringArray &rItems)
{   rItems.RemoveAll(); }

template<>
void to_push_back(const BSTR &rItem, CStringArray &rItems)
{   rItems.Add(rItem); } // implicit CString conversion

// e.g.  ConvertSAFEARRAY<int, std::list<int>>
//       ConvertSAFEARRAY<IDiscussionItemPtr, ListDiscussionItems>
//       ConvertSAFEARRAY<BSTR, CStringArray>
template<typename from, typename to>
void ConvertSAFEARRAY(SAFEARRAY* psaItems, to& rItems)
{
    from* pVals = nullptr;
    HRESULT hr = SafeArrayAccessData(psaItems, (void**)&pVals); // direct access to SA memory

    if (SUCCEEDED(hr))
    {
        long lowerBound, upperBound;  // get array bounds
        hr = SafeArrayGetLBound(psaItems, 1, &lowerBound);
        if (FAILED(hr))
            throw _com_error(hr);

        hr = SafeArrayGetUBound(psaItems, 1, &upperBound);
        if (FAILED(hr))
            throw _com_error(hr);

        to_clear<to>(rItems);
        long cnt_elements = upperBound - lowerBound + 1;
        for (int i = 0; i < cnt_elements; ++i)  // iterate through returned values
        {
            to_push_back<from, to>(pVals[i], rItems);
        }
        hr = SafeArrayUnaccessData(psaItems);
        if (FAILED(hr))
            throw _com_error(hr);
    }
    else
    {
        throw _com_error(hr);
    }

    hr = SafeArrayDestroy(psaItems);
    if (FAILED(hr))
        throw _com_error(hr);
}