web-dev-qa-db-ja.com

C ++のstd :: vectorデータメンバーを持つconstexprメンバー関数

テンプレートパラメーターを返すconstexprメンバー関数をC++クラスに実装しようとしています。コードはc ++ 11互換であると想定されています。しかし、テンプレートクラスにstd :: vectorなどのデータメンバーとしてのSTLコンテナーが含まれていると、コンパイルの問題が発生します(constexprメンバー関数には影響されません)。

最小限の例を次のコードで示します。


#include <vector>
#include <iostream>
#include <array>


template<size_t n>
struct A 
{

  constexpr size_t dimensions() const
  {
    return n;
  }
private:
  std::vector<double> a;
};


int main(int argc,char ** argv)
{
  auto a=A<3>();
  std::array<double,a.dimensions()> arr;

}

コードはコマンドで正しくコンパイルされます

g ++ -std = c ++ 14 -O3 quickTest.cpp -o test -Wall

clang ++ -std = c ++ 11 -O3 quickTest.cpp -o test -Wall

使用すると失敗する

g ++ -std = c ++ 11 -O3 quickTest.cpp -o test -Wall

エラーあり

quickTest.cpp:22:33: error: call to non-‘constexpr’ function ‘size_t A<n>::dimensions() const [with long unsigned int n = 3; size_t = long unsigned int]’
   std::array<double,a.dimensions()> arr;
                     ~~~~~~~~~~~~^~
quickTest.cpp:10:20: note: ‘size_t A<n>::dimensions() const [with long unsigned int n = 3; size_t = long unsigned int]’ is not usable as a ‘constexpr’ function because:
   constexpr size_t dimensions() const
                    ^~~~~~~~~~
quickTest.cpp:22:33: error: call to non-‘constexpr’ function ‘size_t A<n>::dimensions() const [with long unsigned int n = 3; size_t = long unsigned int]’
   std::array<double,a.dimensions()> arr;
                     ~~~~~~~~~~~~^~
quickTest.cpp:22:33: note: in template argument for type ‘long unsigned int’

コードがgcc -std=c++11でコンパイルされず、clang++ -std=c++11でコンパイルされるのはなぜですか?このコードスニペットを、多くの場合c ++ 14/17ではなくc ++ 11のみをサポートするgccの古いバージョンで動作させるにはどうすればよいですか?

Gcc 8.1.1とclang 6.0.1を使用しています

23
Luca Parisi

C++ 11にはルールがありました [dcl.constexpr]/8

...その関数がメンバーであるクラスは、リテラル型(- [basic.types] )。

_struct A_は、vectorのため、リテラルタイプではないため、非静的メンバー関数をconstexprにすることはできません。

したがって、GCCはC++ 11モードでコードを拒否する権利があります。

C++ 14 削除 その制限。

C++ 11の解決策は、dimensions()staticを宣言することです。

_  static constexpr size_t dimensions()
  {
    return n;
  }
_

ライブデモ

20
rustyx