我们正在尝试将一个C17项目从VS 19更新到VS 22,突然之间,我们的代码无法编译了。问题出现在foonathan/memory库的两个头文件中,与我们的代码相距甚远。该库自身的测试在VS 22下编译良好。以我有限的MSVC技能,我无法从错误消息中获得有关实际模板示例化的任何信息,这可能会有所帮助。
这些错误都是error C2065: '<some-identifier>': undeclared identifier
,其中<some-identifier>
是出现在旨在使用SFINAE的decltype
表达式中的函数参数的名称。
4个位置之一是allocator_storage.hpp:140
,摘录如下:
namespace foonathan::memory {
...
template <class StoragePolicy, class Mutex>
class allocator_storage
: FOONATHAN_EBO(StoragePolicy, ...)
{
...
template <class OtherPolicy>
allocator_storage(const allocator_storage<OtherPolicy, Mutex>& other,
FOONATHAN_SFINAE(new storage_policy(other.get_allocator()))) // <--- HERE, this is line 140
: storage_policy(other.get_allocator())
{}
...
};
...
}
我从MSVC得到的完整错误消息没有什么帮助,唯一的额外信息是示例化的模板的名称,没有实际的类型替换:
C:\...\foonathan\memory\allocator_storage.hpp(315): note: see reference to class template instantiation 'foonathan::memory::allocator_storage<StoragePolicy,Mutex>' being compiled
C:\...\foonathan\memory\allocator_storage.hpp(140): error C2065: 'other': undeclared identifier
由于FOONATHAN_SFINAE(Expr)
被定义为decltype((Expr), int()) = 0
(任何地方都看不到任何平台配置),在我看来,这个错误消息显然是错误的--这里有一个明显的other
定义。
我在寻找关于这里发生了什么的任何提示,或者我可以做些什么来帮助理解这个问题。有没有一种方法可以让MSVC打印它正在替换到模板参数中的类型,就像现在的clang和gcc所做的那样?MSVC和基于decltype
的SFINAE在方法参数中是否存在已知的问题?
1条答案
按热度按时间r1zk6ea11#
该问题的最小示例是(live on godbolt;感谢Maciej Polański,此代码基于original reproduction attempt)
clang和gcc都会编译它,但是MSVC在使用C++17 with
/permissive-
(但不在C++17 with/permissive
中,在C++17中等于不指定任何内容)和C++20 (regardless of the permissive flag)时会导致错误。最新的MSVC版本(19.33之后)提供了更多的信息,即
而版本〈=19.33则不会显示此错误消息。不幸的是,它并没有提供更多的信息。
有一些bug reports on developer-community(例如this或this)看起来相关,即使用SFINAE和
decltype
。考虑到所有这些(clang和gcc编译代码;现有的错误报告),我认为这肯定是MSVC中的一个错误。
前面已经提到了一种可能的解决方法,将
decltype
中对参数other
的引用替换为std::declval
(godbolt):我注意到你已经在github上报告了这件事。