MSVC++:模板的 static_assert 不会在 lambda 内触发
Posted
技术标签:
【中文标题】MSVC++:模板的 static_assert 不会在 lambda 内触发【英文标题】:MSVC++: template's static_assert is not triggered inside a lambda 【发布时间】:2018-05-21 03:42:05 【问题描述】:更新 2:
这已在 VS 2019 Preview 16.1 Preview 1 中得到修复。
更新:
我已在visualstudio.com 提交错误报告。
所以我开始研究 C++ 的模板,当我试图阻止使用 static_assert
编译模板类时遇到了这个问题。
基本上,static_assert
错误在 VS2017 上使用 C++ 语言标准:ISO C++17 标准 (/std:c++17) 位于 lambda 内时不会触发。
我也在 gcc-7 上使用 -std=c++17 进行了尝试,并触发了错误。这是 VS2017 上的错误还是我遗漏了什么?
代码示例:
#include <iostream>
#include <string>
#include <type_traits>
template<typename T, typename Enable = void>
class IntegralContainer
static_assert(std::is_integral<T>::value, "Type must be an integral!");
;
template<typename T>
class IntegralContainer<T, typename std::enable_if< std::is_integral<T>::value >::type >
private:
T _value;
public:
IntegralContainer(T value)
: _value(value)
;
int main()
IntegralContainer<int> int_container(1);
// static_assert message is shown here.
// > error C2338: Type must be an integral!
// IntegralContainer<std::string> str_container;
[]()
// static_assert is not triggered here.
IntegralContainer<std::string> str_container;
();
std::cout << "Hello World!\n";
return 0;
【问题讨论】:
来自Godbolt,看起来它甚至在触发错误之前优化了lambda的内容(这将是一个错误)...... 但是如果你给主模板一个带有副作用的默认构造函数,这些副作用确实会发生。 【参考方案1】:它正在优化永远无法执行的代码。 绝对是一个错误。 lambda 正在进行一些(可能是语义替换)基本优化。
生成的程序集显示没有为该行生成代码 IntegralContainer str_container
[]()
00F72280 push ebp
00F72281 mov ebp,esp
00F72283 sub esp,0D8h
00F72289 push ebx
00F7228A push esi
00F7228B push edi
00F7228C push ecx
00F7228D lea edi,[ebp-0D8h]
00F72293 mov ecx,36h
00F72298 mov eax,0CCCCCCCCh
00F7229D rep stos dword ptr es:[edi]
00F7229F pop ecx
00F722A0 mov dword ptr [this],ecx
// static_assert is not triggered here.
IntegralContainer<std::string> str_container;
();
00F722A3 push edx
00F722A4 mov ecx,ebp
00F722A6 push eax
00F722A7 lea edx,ds:[0F722BCh]
00F722AD call @_RTC_CheckStackVars@8 (0F712B2h)
00F722B2 pop eax
00F722B3 pop edx
00F722B4 pop edi
00F722B5 pop esi
00F722B6 pop ebx
00F722B7 mov esp,ebp
00F722B9 pop ebp
00F722BA ret
如果静态断言放在公共 ctor 中。
#include <iostream>
#include <string>
#include <type_traits>
template<typename T, typename Enable = void>
class IntegralContainer
public:
IntegralContainer(T const& value)
static_assert(std::is_integral<T>::value, "Type must be an integral!");
;
template<typename T>
class IntegralContainer<T, typename std::enable_if< std::is_integral<T>::value >::type >
private:
T _value;
public:
IntegralContainer(T value)
: _value(value)
;
int main()
IntegralContainer<int> int_container(1);
// static_assert message is shown here.
// > error C2338: Type must be an integral!
//IntegralContainer<std::string> str_container;
[]()
// static_assert is not triggered here.
IntegralContainer<std::string> str_container(std::string(""));
();
std::cout << "Hello World!\n";
return 0;
static_assert 被触发。
【讨论】:
AFAICT 预处理器在这方面也无可指责。以上是关于MSVC++:模板的 static_assert 不会在 lambda 内触发的主要内容,如果未能解决你的问题,请参考以下文章