MSVC 19.28报C2668重载调用歧义,是否为编译器Bug?
这是MSVC的编译器Bug吗?
答案是肯定的,这属于MSVC在模板重载决议环节引入的回归Bug,你的代码完全符合C++标准,在GCC、Clang以及旧版MSVC(19.10)中正常编译就是最好的证明。
咱们来拆解一下这段代码的重载逻辑:
- 第一个
Foo模板:template<typename T> void Foo(int = {}),当你调用a.Foo<int>()时,模板参数T被显式指定为int,同时使用默认的int{}作为参数,完全匹配函数签名。 - 第二个
Foo模板:template<typename... T, typename... Args> void Foo(Args&&... args),调用时T...被推导为[int],Args...是空参数包,看起来也能匹配无参数调用。
但根据C++标准的重载决议规则,第一个模板更特化,应该被优先选中。MSVC 19.14及之后的版本错误地认为两个重载模板的匹配度相同,从而抛出C2668调用不明确的错误。
你可以通过一些临时手段绕过这个问题,比如:
- 显式传递第一个模板的参数:
a.Foo<int>(0),让第一个模板的匹配度明确高于第二个 - 调整第二个模板的模板参数顺序,比如把
typename... Args放在typename... T之前(不过这会改变模板的语义,需要根据实际需求调整)
内容的提问来源于stack exchange,提问作者Bernd
相关产品推荐
相关产品推荐

