web-dev-qa-db-ja.com

MSVC ++:テンプレートのstatic_assertはラムダ内でトリガーされません

更新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;
}
19
abm

決して実行できないコードを最適化しています。間違いなくバグです。ラムダはいくつかの(おそらく意味論的置換)基本的な最適化を受けています。

結果のアセンブリは、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がトリガーされます。

1
dex black