Search code examples
c++visual-studio-2008calling-convention

Linker error due to "__cdecl" and "__thiscall" Calling convention mismatch when using MFC?


I am using Visual Studio 2008. I am getting the a linker error when building a project that contains a statically linked library only when using MFC CString (vs std::wstring).

So this works:

//header
class FileProcessor
{
    public:
        class iterator;
        friend class iterator;
    //...

    class iterator : public std::iterator<std::input_iterator_tag, std::vector<std::vector<std::wstring>>>
    {
    public:
    //...
    std::vector<std::vector<std::wstring>> operator*() const; 
    }
} 


//cpp 
std::vector<std::vector<std::wstring>> FileProcessor::iterator::operator*() const
{
    return _outerRef->_pimpl->_saxHandler->GetCurrentTable();
}       

But this

//header
#include <afx.h>

class FileProcessor
{
    public:
    class iterator;
    friend class iterator;
    //...

    class iterator : public std::iterator<std::input_iterator_tag, std::vector<std::vector<CString>>>
    {
    public:
        //...
        std::vector<std::vector<CString>> operator*() const; 
    }
} 


//cpp 
std::vector<std::vector<CString>> FileProcessor::iterator::operator*() const
{
    return _outerRef->_pimpl->_saxHandler->GetCurrentTable();
}

gives the linker error:

FileProcessingTests.obj : error LNK2019: unresolved external symbol "public: class
std::vector<class std::vector<class std::basic_string<wchar_t,struct 
std::char_traits<wchar_t>,class std::allocator<wchar_t> >,class std::allocator<class 
std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class 
std::allocator<wchar_t> > > >,class std::allocator<class std::vector<class 
std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class 
std::allocator<wchar_t> >,class std::allocator<class std::basic_string<wchar_t,struct 
std::char_traits<wchar_t>,class std::allocator<wchar_t> > > > > > __thiscall 
FileProcessing::FileProcessor::iterator::operator*(void)const "
(??Diterator@FileProcessor@FileProcessing@@QBE?AV?$vector@V?$vector@V?$basic_string@_WU?
$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits
@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@V?$allocator@V?$vector@V?$basic_string@_WU?$
char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits
@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@@2@@std@@XZ) referenced in function "void 
__cdecl TestUnicodeSingleTable(void)" (?TestUnicodeSingleTable@@YAXXZ)

In both projects, the calling convention is specified as __cdecl in the project file. So why is __thiscall even arising, and how can I fix it? I have to use __cdecl because I am referencing external libraries that use __cdecl.

Additional project settings:

Both projects have these configuration settings:

  • "Use Of MFC" : Use MFC in a Shared DLL
  • "Use Of ATL" : Not Using ATL
  • "Character Set": Use Unicode Character Set

Solution

  • It looks like FileProcessingTests.cpp isn't being rebuilt or it's using a stale header. That object file is still trying to link to the std::wstring variant rather than the CString variant.

    The error message is a verbose way of saying that the unresolved external symbol is for:

    std::vector<std::vector<std::wstring>> FileProcessor::iterator::operator*() const
    

    Keep in mind that std::wstring is just a typedef for:

    class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> >
    

    if you make the default template parameters explicit. The error message is also making the default template parameters for std::vector explicit as well, which is why the error message has such horrendous spew.