Visual Studio中Lambda内的C++14变量模板存在BUG?
解决Visual Studio 2017中Lambda内C++14变量模板失效的问题
你碰到的这个情况其实是Visual Studio 2017对C++14变量模板的Lambda捕获支持存在编译器bug。先看一段能复现问题的示例代码,更直观:
#include <iostream> template<typename T> constexpr T pi = T(3.1415926535897932385); int main() { // Lambda外使用正常,VS2017能输出3.14159 std::cout << pi<double> << std::endl; auto lambda = []() { // Lambda内失效,VS2017输出0.0 std::cout << pi<double> << std::endl; }; lambda(); return 0; }
问题根源
VS2017的编译器在处理Lambda表达式内部的变量模板引用时,没有正确执行模板实例化逻辑,反而错误地将其初始化为对应类型的默认值(比如double的默认值就是0.0)。而GCC 6.3及后续版本已经正确实现了C++14标准中关于变量模板在Lambda内的处理规则,所以能输出预期结果。
可行的解决方案
这里有几种办法可以绕过这个编译器bug:
1. 提前捕获变量模板实例
在Lambda外部先拿到变量模板的实例,再通过值捕获或引用捕获传入Lambda内部使用:
int main() { auto pi_double = pi<double>; auto lambda = [pi_double]() { std::cout << pi_double << std::endl; // 正常输出3.14159 }; lambda(); return 0; }
2. 用函数模板包装变量模板
把变量模板封装成一个函数模板,通过调用函数来获取值,这样Lambda内部就能正确解析:
template<typename T> constexpr T get_pi() { return pi<T>; } int main() { auto lambda = []() { std::cout << get_pi<double>() << std::endl; // 正常输出3.14159 }; lambda(); return 0; }
3. 升级Visual Studio版本
这个bug在Visual Studio 2019及后续版本中已经被官方修复,如果项目允许的话,直接升级到更高版本的VS,就能不用改代码彻底解决问题。
内容的提问来源于stack exchange,提问作者Jonathan Mee
相关产品推荐
相关产品推荐

