MSVC中std::pair默认构造函数的SFINAE实现是否正确?版本变更原因探究
关于VS STL中std::pair默认构造函数实现的疑问解答
首先直接回应你的两个核心问题:
1. VS 15.4.5版本的实现是否正确?
严格来说,这个实现存在潜在的合规性缺陷,并非完全符合C++标准的要求。
你提到的「SFINAE不适用于模板类型参数的默认值」并不完全准确——模板参数推导时,若类型模板参数的默认实参代入后产生无效类型(比如enable_if_t条件不满足),确实会触发SFINAE排除该重载。但这个写法的漏洞在于:如果有人显式指定该构造函数的模板参数_Uty1和_Uty2,默认实参就会被跳过,enable_if的检查会直接被绕过。
虽然std::pair的常规使用场景中几乎没人会这么做,但根据C++标准草案n4659的23.4.2节,要求这个默认构造函数仅当first_type和second_type均为可默认构造时才参与重载决议——这个约束是无条件的,不管用户是否显式指定模板参数。15.4.5的实现无法满足这个无条件约束,因此存在合规性问题。
2. 修改为15.5.3版本的意义何在?
15.5.3版本的写法是更标准、更可靠的SFINAE实现方案,彻底解决了旧版本的漏洞:
- 它将
enable_if_t放在非类型模板参数的默认值中(enable_if_t<..., int> = 0),而非类型模板参数的默认值会依赖于前面的_Uty1和_Uty2。无论编译器自动推导模板参数,还是用户显式指定_Uty1和_Uty2,都会触发enable_if的条件检查——只要任一类型不可默认构造,整个模板构造函数就会被SFINAE排除,无法参与重载决议。 - 这种写法完全贴合标准要求,确保只有当
first_type和second_type都可默认构造时,该构造函数才会存在,彻底避免了误用或绕开检查的可能性。 - 新版本使用
conjunction_v替代了旧版本的&&连接写法,这是C17引入的更简洁的特性,语义完全一致但更符合现代C的代码风格。
内容的提问来源于stack exchange,提问作者Edgar Rokjān
相关产品推荐
相关产品推荐

