'TypeInfo <char>(char*)'未定义但在C++ 11之前工作; 什么改变了,我该如何修复错误?

ASt*_*her 9 c++ c++11 c++03 visual-studio-2015

我正在尝试从Crysis Wars SDK中的源代码构建DLL,并且在过去的Visual Studio早期版本(即2005年,2008年和2010年)上已经成功完成了.我的具体问题是:

Error   4   error LNK2019: unresolved external symbol "struct CTypeInfo const & __cdecl
TypeInfo<char>(char *)" (??$TypeInfo@D@@YAABUCTypeInfo@@PAD@Z) referenced in function 
"void __cdecl SwapEndian<char>(char *,unsigned int)" (??$SwapEndian@D@@YAXPADI@Z)   
G:\Noctis\Mods\Noctis\Code\GameCVars.obj    GameDll
Run Code Online (Sandbox Code Playgroud)

我试图在Visual Studio中清理代码并在可能的情况下重建它,但这并没有改变任何东西.

我在这里遗漏了什么,或者从C++ 03到C++ 11有什么变化,这意味着如果没有恢复到旧版本的C++,这段代码就不再可编译了?

我已经在64位和32位上成功地在Visual Studio 2010上编译了此代码,因此它必须是与将项目迁移到Visual Studio 2015相关的一些问题.

在2012年,2013年和2015年版本的Visual Studio上进行编译会重现此错误,但不会重现2010年,因此似乎在C++ 11中引入了触发此问题的更改.

我究竟做错了什么?

阅读mem-fun的答案不是std的成员,它可能只是我需要包含一个标准库,我不需要在早期版本的Visual Studio中包含它.如果这是真的,我需要哪个库#include

我也创建了一个GitHub的库只包含SDK中提供的原始未修改的代码,用于测试目的(在我自己做了一个错字,这似乎并没有在这里是如此的事件,但我在这里为把链接它可能会有所帮助).

如果重要,我在Windows 10 Professional x64上使用Visual Studio 2015企业版.

Yir*_*kha 4

错误是什么意思?

该错误消息暗示了一个经典的“已声明但未定义”场景。

TypeInfo<char>(char*)在 TypeInfo.h 中声明(通过一些宏)并在AutoTypeInfo.cpp项目 CryCommon 中声明。

通常,您只需确保 CryCommon 项目已正确构建并正确链接到最终的 GameDll 项目即可。

但事实证明,CryCommon 项目已经构建了很长时间了 - 它引用了许多其他 Crytek 库等。所以问题一定是现在有些东西需要这些TypeInfo<>定义,而以前不需要。

引用的代码是什么TypeInfo<>

在您的项目中,它的功能CmdHelp()在 Aurora/Code/GameCVars.cpp 中,正是这一行:

nRead = gEnv->pCryPak->FRead( buf, BUFSZ, f );
Run Code Online (Sandbox Code Playgroud)

该方法的实现FRead()在CryCommon/ICryPak.h中:

template<class T>
size_t FRead(T *data, size_t elems, FILE *handle, bool bSwap = true)
{
    size_t count = FReadRaw(data, sizeof(T), elems, handle);
    if (bSwap)
        SwapEndian(data, count);
    return count;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,如果bSwap为 true(默认值),SwapEndian()则会在那里调用。

为什么以前没有表现出这一点?

也许编译器的行为确实不同。

或者,更有可能的是,您之前一直将项目编译为Release。整个字节交换功能仅在大端系统(并且您的目标很可能不是其中之一)或调试期间启用 - 然后字节实际上交换两次以测试相关代码(请参阅 CryCommon/Endian.h) 。

可以采取什么措施来修复它?

您现在有多种选择:

  • 继续仅作为发布版本进行编译(可能和以前一样)。也许您永远不会在调试器中调试代码。

  • 只需将代码中的交换调用注释掉即可FRead()。无论如何,您正在使用它来加载文本文件,没有必要交换字符。

  • ...


FWIW,我必须做的其他事情才能使您的代码编译:

  • 查看“Broken”之前的较早提交
  • 加载 Mods\Aurora\Code\Aurora.sln
  • 删除不存在的 .vcprojx 项目
  • 再次添加所有3个.vcproj文件,让它们转换为VS2015的
  • 对于 GameDll 项目,添加预处理器定义_SILENCE_STDEXT_HASH_DEPRECATION_WARNING
  • 对于 GameDll 项目,设置启用 C++ 异常处理/EHsc
  • 把上面的代码注释掉