如果我的模板类型首先作为 lambda 参数出现,MSVC 会引发一个奇怪的错误
Posted
技术标签:
【中文标题】如果我的模板类型首先作为 lambda 参数出现,MSVC 会引发一个奇怪的错误【英文标题】:If my templated type occurs firstly as a lambda argument, MSVC raises a strange error 【发布时间】:2017-06-01 12:29:45 【问题描述】:考虑这段代码:
#define SOLUTION 0
template <class T>
constexpr int one = 1;
template <class T>
struct A
static constexpr int o = one<A<T>>;
void call()
static_assert(one<A<T>> == 1, "Failure");
;
int main()
#if SOLUTION
A<int> object;
#endif
[](A<int> a)
a.call();
;
return 0;
无论SOLUTION
定义的值如何,它都会成功构建here on ideone。
现在,我知道这段代码没有什么实际意义,但那是因为我正在认真地尝试找到这种奇怪行为的最小工作示例。如果我使用最新的 Visual Studio 2017(平台工具集 v141,_MSC_VER = 1910)构建它,我会收到以下错误:
1>source.cpp(11): error C2131: expression did not evaluate to a constant
1>source.cpp(11): note: failure was caused by a read of an uninitialized symbol
1>source.cpp(11): note: see usage of 'one<A<int>>'
1>source.cpp(10): note: while compiling class template member function 'void A<int>::call(void)'
1>source.cpp(21): note: see reference to function template instantiation 'void A<int>::call(void)' being compiled
1>source.cpp(21): note: see reference to class template instantiation 'A<int>' being compiled
有趣的是,当我为 SOLUTION
宏设置 1 时,它会成功构建。唯一的区别是在编译器到达 lambda 定义之前,main
的作用域中定义了一个未使用的 A<int> object;
变量。
如果在 main 之前定义一个这样的函数也很好:
void f(A<int>& a)
a.call();
事实上它和变量定义一样很好地解决了这个问题。
是编译器的错误还是上面的代码块违反了标准?
【问题讨论】:
在 VS2017 更新 3 上编译,但不在 (RTM) 更新 2 上编译。 @Ajay Strange,我的 VS2017 版本似乎是最新的,于 5 月 30 日更新,因此实际上是 3 天前。也许它是否是社区版本很重要(我的是社区)?我也注意到这里的问题的开发人员:developercommunity.visualstudio.com/content/problem/63753/… 我也确认它不会发生在我自己的机器上。 我已经安装了更新 3 的预览版,它有很多 C++17 特性。 @Ajay 哇,不知道预览!我马上试试看。 【参考方案1】:引用Ajay:
在 VS2017 更新 3 上编译,但不在 (RTM) 更新 2 上编译
我也在我的机器上确认了这种行为。这意味着相关的更正已经存在,并且很快就会引入生产版本本身,所以我认为这个错误不值得进一步关注。
【讨论】:
以上是关于如果我的模板类型首先作为 lambda 参数出现,MSVC 会引发一个奇怪的错误的主要内容,如果未能解决你的问题,请参考以下文章