更新2:
これは、VS2019プレビュー16.1プレビュー1で修正されました。
更新:
visualstudio.com にバグレポートを提出しました。
そのため、C++のテンプレートを使い始めましたが、static_assert
を使用してテンプレートクラスがコンパイルされないようにしようとすると、この問題が発生しました。
基本的に、static_assert
エラーは、C++言語標準:ISO C++ 17標準(/ std:c ++ 17)を使用してVS2017のラムダ内にある場合はトリガーされません。
-std = c ++ 17を使用してgcc-7でもこれを試したところ、エラーがトリガーされました。これは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;
}
決して実行できないコードを最適化しています。間違いなくバグです。ラムダはいくつかの(おそらく意味論的置換)基本的な最適化を受けています。
結果のアセンブリは、IntegralContainerstr_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がトリガーされます。