Reputation: 309
When I went through std::vector
over at cppreference.com and found a section called "Member types" I did not understand what that means. In fact the member types section is present in all the reference documents of containers in stl
library.
Can someone help me in understanding this?
Upvotes: 6
Views: 855
Reputation: 16419
The member types define the types that are used by the vector object. Many standard containers use member types to describe the types used, so that the programmer does not need to figure them out manually. This is particularly useful when working with complex templates, where types may be hard to determine.
For example, the return type of std::vector<___>::size()
is usually std::size_t
, however another C++ vector implementation may return a different integer type (e.g. int32_t
). Instead of assuming what types you need in your code (and possibly introducing dangerous casting), you can simply use the member types exposed by the vector to write your code with the perfect types every time. For example:
std::vector<int> vec;
const std::vector<int>::value_type val = 4;
// std::vector<int>::value_type is a typedef of int!
vec.push_back(val);
const std::vector<int>::size_type size = vec.size();
// std::vector<int>::size_type is a typedef of std::size_t, usually.
const std::size_t size2 = vec.size();
// same as above, but we assume that vec.size() returns a size_t.
// If it does not, we may cause a narrowing conversion!
for (std::vector<int>::const_iterator it = vec.begin(), end = vec.end(); it != end; ++it)
{
// The const_iterator type is also a member type of vector.
std::cout << *it << std::endl;
}
Iterators are probably the most common usage of member types in standard containers. Rather than having to figure out if an iterator is a random access iterator, or a simple forward iterator, or any other kind of iterator, we can just use the iterator
member type exposed by the container.
The C++11 auto
keyword can take this even further. Instead of doing:
const std::vector<int>::size_type size = vec.size();
we can now just do:
const auto size = vec.size();
and the compiler will automatically work it out.
Generally speaking most C++ standard objects will use the same member types where possible (e.g. size_t
for size_type
, T
for value_type
, T&
for reference_type
), but it is not guaranteed (iterator
member type is different for std::vector
and std::list
, because their implementations are wildly different and they cannot use the same iterator type).
Upvotes: 8
Reputation: 96256
There are two things you need to understand:
For example,
using blah = int;
would make blah
an alias for int
. In other words, you would be able to use blah
instead of int
in any place.
(There is another way to make a type alias using typedef
instead of using
, but it is less readable.)
For example, if you declared a following struct
struct S
{
using type = int;
};
you would be able to use S::type
instead of an int.
Such aliases inside of classes are often called member types.
Upvotes: 0
Reputation: 24249
The page you linked lists a "member type" of "value_type T". This is type definition that belongs to or is a member of T. Consider
using VEC = std::vector<double>;
VEC dv { 4.2 };
Now lets say we want to store a value from dv
but we don't want to hard-code the type so that a future change to the definition of VEC
will Do The Right Thing (TM).
using VEC = std::vector<double>;
VEC dv { 4.2 };
// ...
VEC::value_type d = dv.front();
Or if you want to write cross-platform portable code, it can be helpful to use 'size_type' to ensure you store sizes that are large enough:
int s = dv.size(); // wrong on 64-bit system
VEC::size_type s = dv.size(); // always correct
That is to say, std::vector<double>
hosts a type definition, value_type
, which evaluates to the type of 'T' in vector, or in our case double.
This is mostly important for generic programming:
template<typename T>
void dothing(const T& container)
{
T::const_pointer* c = &container; // for some reason I need it's address
// .. other stuff
}
Upvotes: 1
Reputation: 477040
Here's a typical class in C++:
struct Foo
{
int n; // non-static data member
static const float x; // static data member
int f() const; // non-static member function
static int g(); // static member function
template <typename T>
void h(T); // non-static member function template
struct X { bool a; }; // member type
template <typename> struct Q; // member class template
using T = Q<int>; // member type (member typedef)
};
Example usage:
// Use static members
print(Foo::x);
print(Foo::g());
Foo::X y;
Foo::Q<double> z;
Foo::T w;
// Use non-static members (requires instance)
void demo(const Foo & a)
{
print(a.n);
print(a.f());
print(a.h<float>());
}
Upvotes: 3