VS2017编译WRL的Callback模版函数兼容性问题及解决方法

近来一直在研究DXR的示例代码,并在其中看到例子中大量的使用了WRL的新模版类代替ATL的老三样的模版类,使用最多的就是COM智能指针Microsoft::WRL::ComPtr类。在聚合使用D3D的接口时,更是像下面这样大量应用该模版包装了D3D的接口:

......
Microsoft::WRL::ComPtr<IDXGIFactory4>               m_dxgiFactory;
Microsoft::WRL::ComPtr<IDXGISwapChain3>             m_swapChain;
Microsoft::WRL::ComPtr<ID3D12Resource>              m_renderTargets[MAX_BACK_BUFFER_COUNT];
Microsoft::WRL::ComPtr<ID3D12Resource>              m_depthStencil;
// Presentation fence objects.
Microsoft::WRL::ComPtr<ID3D12Fence>                 m_fence;
UINT64                                              m_fenceValues[MAX_BACK_BUFFER_COUNT];
Microsoft::WRL::Wrappers::Event                     m_fenceEvent;
// Direct3D rendering objects.
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>        m_rtvDescriptorHeap;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>        m_dsvDescriptorHeap;
......

使用ComPtr包装这些接口的好处就不赘述了,我只是处于对新事物的强烈好奇与推崇,就试图在自己的代码中也引用WRL中的模版类。于是我依葫芦画瓢在我的头文件中加入了简单的一句:

#include <wrl.h>

可是直接编译却报了如下莫名其妙的错误:

c:\\program files (x86)\\windows kits\\10\\include\\10.0.17134.0\\winrt\\wrl\\event.h(316): error C7510: “Callback”: 模板 从属名称的使用必须以“模板”为前缀

c:\\program files (x86)\\windows kits\\10\\include\\10.0.17134.0\\winrt\\wrl\\event.h(324): error C7510: “Callback”: 模板 从属名称的使用必须以“模板”为前缀

双击查看代码如下:

template<typename TDelegateInterface, typename TLambda>
ComPtr<typename Details::DelegateArgTraitsHelper<TDelegateInterface>::Interface> Callback(TLambda&& callback) throw()
{
    using DelegateHelper = Details::DelegateArgTraitsHelper<TDelegateInterface>;
    return DelegateHelper::Traits::Callback<TDelegateInterface
        , typename DelegateHelper::Interface>(Details::Forward<TLambda>(callback));
}

从代码分析大概了解这个Callback的模版函数因为又使用了一个lambda函数的参数callback,但是上下文中的模版参数定义只是说这是个类型名,这样在调用Callback的时候编译器就不知道使用Callback的哪个具体模版了,但其实这是个伪错误,根本原因就是在VS2017中,VC++的编译器默认打开了一个开关选项:/permissive-,具体如下图所示:

这个选项的含义根据MSDN的说法是这样:

/permissive-:启用所有严格标准符合性编译器选项,并禁用大部分特定于 Microsoft 的编译器扩展(但有一些例外,比如 __declspec(dllimport))。 在 Visual Studio 2017 15.5 版中此选项默认为开启状态。 /permissive- 符合性模式包括对两阶段名称查找的支持。

当然一如既往的MSDN的这个解释是看不懂的,但大意就是说这个开关打开后好多语言扩展就不能用了,这也是为了适应跨平台跨编译器编译Windows C++代码做的检查。但是这个开关就拦住了WRL里的上述Callback模版函数的调用,最终引起上述的哪个编译错误。

知道了问题的症结,那么修改就不难了,只需要将这个开关关闭即可,如下图:

最终点击确定,编译,一次就通过了!当然后果可能就是对其他的C++编译器来说可能就没法编过了,当然我们使用的本来就是Windows的WRL模版类,推荐使用VC++编译器,不兼容就不兼容吧。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片