web-dev-qa-db-ja.com

vector :: value_typeのサイズを取得するにはどうすればよいですか?

ベクトルに含まれているタイプのsizeofを取得したいと思います。これが私が試したものです:

#include <iostream>
#include <vector>

int main()
{
    std::vector<uint> vecs;
    std::cout << sizeof(vecs.value_type) << std::endl;
    return 0;
}

私の理解では、これは正しいはずです。ただし、GCC 4.8.1でコンパイルすると、次のようになります。

test-sizeof.cpp:関数 'int main()':
 test-sizeof.cpp:7:27:エラー: 'std :: vector <unsigned int> :: value_type' [の使用が無効です。 ____。] std :: cout << sizeof(vecs.value_type)<< std :: endl; 
 ^

私は何が間違っているのですか?含まれているタイプのサイズを取得するにはどうすればよいですか?

23
Chris

3.4.3修飾名ルックアップ[basic.lookup.qual]

1クラスまたは名前空間のメンバーまたは列挙子の名前は、そのクラス、名前空間、または列挙型を示すネストされた名前指定子に適用された::スコープ解決演算子(5.1)の後に参照できます。ネストされた名前指定子の::スコープ解決演算子の前にdecltype指定子がない場合、::の前の名前のルックアップでは、名前空間、タイプ、および特殊化されたテンプレートのみが考慮されます。タイプです。見つかった名前が名前空間、クラス、列挙型、または依存型を指定していない場合、プログラムの形式は正しくありません。

この場合、クラステンプレートの特殊化_std::vector<uint>_からtypeメンバーにアクセスしており、次のように記述する必要があります。

_std::vector<uint>::value_type
_

あなたが実際にテンプレート化されたコードの中にいて、例えば同じネストされたタイプにアクセスするには、次のようにキーワードtypenameをプレフィックスとして付ける必要があります。

_typename std::vector<T>::value_type
_

C++ 11では、sizeof(decltype(vecs)::value_type)またはsizeof(decltype(vecs.back()))を使用できます。後者は、型の正確な名前がわからないが、を介してそれらにアクセスする方法を知っている場合に便利です。 back()のようなメンバー関数。

:@ Caseyがコメントで指摘しているように、decltypeは、型自体を取得するために参照を削除する必要がありますが、sizeofの場合関係ない目的。

15
TemplateRex

メンバーアクセス演算子.は、データメンバーとクラスのメンバー関数にアクセスするためにのみ使用でき、タイプ名などの他のネストされた名前にはアクセスできません。それらにアクセスするには、スコープ解決演算子::が必要です。これは、クラスタイプのオブジェクトではなく、クラス名(またはエイリアス)にのみ適用できます。

std::vector<uint>::value_type

C++ 11以降では、オブジェクトがあり、型への便利なアクセスがない場合、decltypeで型名を指定できます。

decltype(vecs)::value_type
9
Mike Seymour

コメントはほとんどすべてを述べています:ベクトルのタイプがわかっている場合は、sizeof(std::vector<uint>::value_type)を使用できます。それ以外の場合は、sizeof(decltype(vecs)::value_type)を使用します。

decltypeはその引数の型に評価される魔法のC++ 11構造であるため、コードは

int i;
float f;

decltype(i) j;
decltype(f) g;

と同じです

int i;
float f;

int j;
float g;

フィールドとメソッドには.演算子のみを使用してください(技術的には静的変数にも使用できますが、これは悪い習慣と見なされます)。静的変数、内部クラス、クラススコープテンプレートパラメーターまたはtypedef(value_typeなど)など、その他の場合は、スコープ解決演算子::を使用します。

私はもっ​​と簡潔な方が好きです:

_sizeof(vecs[0])
_

vecsが長さゼロのベクトルの場合はどうなるので、一見安全ではないように見えるのはどれですか?

sizeof()演算子の引数が値型で呼び出されるこの例では、sizeof()演算子はコンパイル時に実行されるため、_vecs[0]_がセグメンテーション違反やクラッシュを引き起こすことはありません。 。

p.s. sizeof()は、引数が可変長配列(CまたはGNU C++拡張)から)の場合にのみ実行時に評価されます。

3