I want to get sizeof
of the type that is contained in a vector. Here is what I tried:
#include <iostream>
#include <vector>
int main()
{
std::vector<uint> vecs;
std::cout << sizeof(vecs.value_type) << std::endl;
return 0;
}
From my understanding this should be correct. However, when compiling with GCC 4.8.1 this is what I get:
test-sizeof.cpp: In function ‘int main()’:
test-sizeof.cpp:7:27: error: invalid use of ‘std::vector<unsigned int>::value_type’
std::cout << sizeof(vecs.value_type) << std::endl;
^
What am I doing wrong? How can I get the size of the contained type?
3.4.3 Qualified name lookup [basic.lookup.qual]
1 The name of a class or namespace member or enumerator can be
referred to after the :: scope resolution operator (5.1) applied to a
nested-name-specifier that denotes its class, namespace, or
enumeration. If a :: scope resolution operator in a
nested-name-specifier is not preceded by a decltype-specifier, lookup of
the name preceding that :: considers only namespaces, types, and
templates whose specializations are types. If the name found does not
designate a namespace or a class, enumeration, or dependent type, the
program is ill-formed.
In this case, you are accessing a type
member from the class template specialization std::vector<uint>
, and you need to do it by writing:
std::vector<uint>::value_type
In case you are actually inside templated code and want to e.g. access the same nested type, you need to prefix it with the keyword typename
like this:
typename std::vector<T>::value_type
In C++11, you can use sizeof(decltype(vecs)::value_type)
or also sizeof(decltype(vecs.back()))
, the latter is convenient if you don't know the precise name of the type but know how to access them through a member function like back()
.
Note: as pointed out by @Casey in the comments, decltype
requires stripping references in order to get the type itself, but for sizeof purposes that doesn't matter.
The member access operator .
can only be used to access data members and member functions of classes, not other nested names such as type names. You'll need the scope resolution operator ::
to access them, and that can only be applied to the class name (or an alias), not an object of class type:
std::vector<uint>::value_type
In C++11 or later, decltype
can give you a type name, if you have an object and no convenient access to the type:
decltype(vecs)::value_type
The comments pretty much said it all: if you know the type of the vector, you can use sizeof(std::vector<uint>::value_type)
. Otherwise use sizeof(decltype(vecs)::value_type)
.
decltype
is a magical C++11 construct that evaluates to the type of its argument, so the code
int i;
float f;
decltype(i) j;
decltype(f) g;
Is the same as
int i;
float f;
int j;
float g;
Only use the .
operator for fields and methods (technically it can be used for static variable as well, but it's considered bad practice). For anything else, such as static variables, inner classes, or class-scope template parameters or typedefs (such as value_type
), use the scope-resolution operator ::
.
I prefer the more concise:
sizeof(vecs[0])
Which at first glance seems unsafe because what happens when vecs
is a zero length vector?
For this example where the argument to sizeof()
operator is called on a value type, the sizeof()
operator is executed at compile time and so vecs[0]
can never cause a segfault or crash.
p.s. sizeof()
is only evaluated at runtime when the argument is a variable-length-array (from C or GNU C++ extension)