MSVC中std::variant结合折叠表达式的static_assert失败问题
MSVC下
is_of函数断言失败的原因分析 问题背景
以下代码实现了一个is_of函数,用于判断std::variant存储的值是否匹配指定类型,在GCC和Clang中运行正常,但在MSVC中标记为“Fails”的两个static_assert断言会失败,改用if constexpr展开折叠表达式后恢复正常:
#include <variant> class A {}; class B {}; template<typename... Ts, typename Variant> bool constexpr is_of(const Variant& variant) { return std::visit( [](const auto& v) { using V = std::decay_t<decltype(v)>; return (std::is_same_v<V, Ts> || ...); }, variant); } int main() { using Variant = std::variant<A, B>; static_assert(is_of<A>(Variant{A{}})); static_assert(!is_of<B>(Variant{A{}})); static_assert(is_of<B>(Variant{B{}})); // Fails static_assert(!is_of<A>(Variant{B{}})); // Fails static_assert(!is_of<int>(Variant{A{}})); static_assert(!is_of<int>(Variant{B{}})); return 0; }
失败原因
MSVC对泛型lambda内的折叠表达式处理存在实现差异:
- 当
std::visit实例化泛型lambda时,MSVC错误地将折叠表达式(std::is_same_v<V, Ts> || ...)的结果视为不依赖于lambda模板参数V的常量值,而非针对每个V类型单独计算结果。 - 例如调用
is_of<B>(Variant{B{}})时,MSVC可能错误复用了针对A类型计算的折叠表达式结果(false),而非针对B类型计算出正确的true,导致断言失败。
改用if constexpr后,编译期会明确根据当前V的类型选择分支,MSVC会为每个V类型生成独立的代码逻辑,从而正确计算匹配结果。
内容的提问来源于stack exchange,提问作者pasbi
相关产品推荐
相关产品推荐

