仅Visual Studio创建std::promise<std::tuple<T>>报C2512错误是什么原因
问题根因
这是旧版本MSVC(Visual C++)标准库的实现合规性缺陷,不符合C++标准的要求。
C++标准明确规定:std::promise的构造函数不需要其模板参数类型支持默认构造,仅在调用std::promise::set_value方法时才需要对应类型符合构造要求。
触发编译错误的具体原因如下:
- 你使用的VS2019 16.7版本配套的MSVC 14.27 STL实现中,内部存储promise与future共享状态的
_Associated_state类构造函数,错误地尝试对存储的元素执行默认构造,即使该默认构造逻辑没有任何实际作用、后续set_value调用会直接覆盖构造好的对象。 - 测试类
Foo显式删除了默认构造函数,导致std::tuple<Foo>的默认构造函数也被隐式删除,刚好触发MSVC内部的非法构造调用,抛出编译错误。 - Clang配套的libc++、GCC配套的libstdc++的
std::promise实现均采用惰性初始化机制存储元素,仅在set_value调用时才会构造对象,不会触发不必要的默认构造要求,因此代码可以正常编译。
可行修复方案
- 升级Visual Studio工具链:VS2019 16.10及以上版本、所有VS2022版本的MSVC STL都已经修复了该问题,升级后原代码可直接正常编译。
- 若无法升级工具链,可采用以下临时兼容方案:
- 将promise的元素类型替换为
std::optional<std::tuple<Foo>>,利用std::optional的惰性初始化特性绕开默认构造要求 - 用
std::unique_ptr<std::tuple<Foo>>作为promise的元素类型,通过堆分配手动控制对象构造时机
内容的提问来源于stack exchange,提问作者Quentamia
相关产品推荐
相关产品推荐

