错误 C2664:无法将参数 2 从 'const ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *' 转换为 'ATL::CAdapt&l

Posted

技术标签:

【中文标题】错误 C2664:无法将参数 2 从 \'const ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *\' 转换为 \'ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *\'【英文标题】:error C2664: cannot convert argument 2 from 'const ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *' to 'ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *'错误 C2664:无法将参数 2 从 'const ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *' 转换为 'ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *' 【发布时间】:2014-05-13 11:01:24 【问题描述】:

我正在将 VS2008(VC++) 代码迁移到 VS2013。我收到以下错误:

error C2664: 'HRESULT _CopyItfFromAdaptItf<IZipFileEntry>::copy(T **,ATL::CAdapt<ATL::CComPtr<T>> *)' : cannot convert argument 2 from 'const ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *' to 'ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *'

Visual Studio SDK 文件中出现错误,怎么可能?我无法修复此错误。请在下面的输出和错误行下方找到。

非常感谢您的帮助!

输出:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\atlmfc\include\atlcom.h(5818): error C2664: 'HRESULT _CopyItfFromAdaptItf<IZipFileEntry>::copy(T **,ATL::CAdapt<ATL::CComPtr<T>> *)' : cannot convert argument 2 from 'const ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *' to 'ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *'
      with
      [
          T=IZipFileEntry
      ]
      Conversion loses qualifiers
      C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\atlmfc\include\atlcom.h(5803) : while compiling class template member function 'HRESULT ATL::ICollectionOnSTLImpl<IZipFileDir1,EntryList,IZipFileEntry *,_CopyItfFromAdaptItf<IZipFileEntry>,EntryEnum>::get_Item(long,ItemType *)'
      with
      [
          ItemType=IZipFileEntry *
      ]
      C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\atlmfc\include\atlcom.h(5140) : see reference to class template instantiation 'ATL::ICollectionOnSTLImpl<IZipFileDir1,EntryList,IZipFileEntry *,_CopyItfFromAdaptItf<IZipFileEntry>,EntryEnum>' being compiled

错误代码:

if (iter != m_coll.end())
      hr = CopyItem::copy(pvar, &*iter); // Error C2664
return hr;

P.S:我无法编辑和保存这个 atlcom.h 文件。我访问路径被拒绝错误消息。这是因为它是一个 SDK 文件吗?

添加了更多代码定义:

struct _CopyItfFromAdaptItf 
    static HRESULT copy(T** p1, CAdapt< CComPtr<T> >* p2) 
    if( *p1 = p2->m_T ) return (*p1)->AddRef(), S_OK;
    return E_POINTER;



IZipFileEntry : public IDispatch

    public:
        virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_name( 
        /* [retval][out] */ BSTR *pVal) = 0;

        virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_lastModified( 
        /* [retval][out] */ DATE *pVal) = 0;

        virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_fileSize( 
        /* [retval][out] */ long *pVal) = 0;

        virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_compressedSize( 
        /* [retval][out] */ long *pVal) = 0;

    ;


typedef ICollectionOnSTLImpl<IZipFileDir1, EntryList, IZipFileEntry*, _CopyItfFromAdaptItf<IZipFileEntry>, EntryEnum> EntryCollection;

ICollectionOnSTLImpl 的定义

class ICollectionOnSTLImpl : 
    public T

public:
        STDMETHOD(get_Count)(_Out_ long* pcount)
        
        if (pcount == NULL)
            return E_POINTER;
        ATLASSUME(m_coll.size()<=LONG_MAX);

        *pcount = (long)m_coll.size();

        return S_OK;
    
    STDMETHOD(get_Item)(
        _In_ long Index, 
        _Out_ ItemType* pvar)
    
        //Index is 1-based
        if (pvar == NULL)
            return E_POINTER;
        if (Index < 1)
            return E_INVALIDARG;
        HRESULT hr = E_FAIL;
        Index--;
        CollType::const_iterator iter = m_coll.begin();
        while (iter != m_coll.end() && Index > 0)
        
            iter++;
            Index--;
        
        if (iter != m_coll.end())
            hr = CopyItem::copy(pvar, &*iter);
        return hr;
    
    STDMETHOD(get__NewEnum)(_Outptr_ IUnknown** ppUnk)
    
        if (ppUnk == NULL)
            return E_POINTER;
        *ppUnk = NULL;
        HRESULT hRes = S_OK;
        CComObject<EnumType>* p;
        hRes = CComObject<EnumType>::CreateInstance(&p);
        if (SUCCEEDED(hRes))
        
            hRes = p->Init(this, m_coll);
            if (hRes == S_OK)
                hRes = p->QueryInterface(__uuidof(IUnknown), (void**)ppUnk);
        
        if (hRes != S_OK)
            delete p;
        return hRes;
    
    CollType m_coll;
;

【问题讨论】:

是的,因为它是一个 SDK 文件,您绝对不应该更改它们。您显然是在向想要更改所述变量的函数提供指向 const 变量的指针。查看模板错误,直到找到导致问题的代码行。最难解密的模板错误解释了为什么 ATL 如此烦人;) 它表示该行代码正在尝试写入您不应该写入的位置。可能是对的。 实际上我收到一条错误消息,指出找不到/无法打开“atlimpl.cpp”。根据以下链接中的建议 social.msdn.microsoft.com/Forums/en-US/… ,我评论了 #include 行,然后在构建时出现此错误。 commeted #include 是否不正确? 另外,请注意,在 VS 2008 中作为 sdk 文件一部分的“atlimpl.cpp”在 VS 2013 中不再存在 @RaymondChen:ICollectionOnSTLImpl 在 atlcom.h 中,所以他最好不要更改它。 【参考方案1】:

如果没有所有代码,很难确定,但看起来我已经用以下代码重现了这个问题:

template<class T>
struct _CopyItfFromAdaptItf 
    static HRESULT copy(T** p1, CAdapt< CComPtr<T> >* p2) 
        if( *p1 = p2->m_T ) return (*p1)->AddRef(), S_OK;
        return E_POINTER;
    
;

IDispatch** disp;
const CAdapt<CComPtr<IDispatch>> adapt; // note const here
_CopyItfFromAdaptItf<IDispatch>::copy( disp, &adapt ); //error C2664 here

编译器输出是

File(Line) : error C2664: '_CopyItfFromAdaptItf<T>::copy' :
  cannot convert parameter 2 from 'const ATL::CAdapt<T> *' to 'ATL::CAdapt<T> *'
    with
    [
      T=IDispatch
    ]
    and
    [
      T=ATL::CComPtr<IDispatch>
    ]
    and
    [
      T=ATL::CComPtr<IDispatch>
    ]
    Conversion loses qualifiers

这与您引用的输出非常匹配。

问题是_CopyItfFromAdaptItf::copy() 想要一个指向非常量的指针,但传递了一个指向 const 的指针。将指针传递给 const 的代码位于属于 SDK 头文件的 atlcom.h 中,因此您最好不要更改它。

如果 _CopyItfFromAdaptItf::copy() 签名被更改为接受指向 const 的指针:

static HRESULT copy(T** p1, const CAdapt< CComPtr<T> >* p2) // note addition of const

它仍然编译得很好。 _CopyItfFromAdaptItf 不在 ATL 标头中,所以我猜它在您的代码中,您可以更改它。

所以看起来解决方案是简单地更改_CopyItfFromAdaptItf::copy() 以接受指向 const 的指针,问题就会消失。

【讨论】:

以上是关于错误 C2664:无法将参数 2 从 'const ATL::CAdapt<ATL::CComPtr<IZipFileEntry>> *' 转换为 'ATL::CAdapt&l的主要内容,如果未能解决你的问题,请参考以下文章

error C2664: “StrCmpW”: 不能将参数 2 从“const char [12]”转换为“PCWSTR”

错误 C2664:无法将参数 1 从“int”转换为“int (__cdecl *)(int)”

错误 C2664:无法将参数 1 从“int”转换为“int []”

错误 C2664:“SQLGetData”:无法将参数 6 从“SDWORD *”转换为“SQLLEN *”

求助:error C2664: “CreateWindowExW”: 不能将参数 3 从“const char [8]”转换为“LPCWSTR”

error C2664: “int CWnd::GetWindowTextW(LPTSTR,int) const”: 不能将参数 1 从“char [10]”转换为“LP