Reputation: 781
The following code is illegal:
#include <vector>
#include <utility>
int main() {
std::vector<std::pair<int, char> > v;
v.push_back(v.value_type(0, 'a')); // *
}
I have to change * to
v.push_back(decltype(v)::value_type(0, 'a'));
for the code to work.
Why is the line marked * not allowed? What is the reason behind that rationale?
Upvotes: 4
Views: 447
Reputation: 5766
v
is an object, and v.value_type
is attempting to access value_type
as though it's a member of the object. That's incorrect because value_type
belongs to the class, not the instance. (As a side note, typedefs always belong to the class because they are fixed at compile time... i.e. different instances can't have different copies.)
decltype(v)
resolves to the underlying class type of the object v
, so in this case it's equivalent to writing std::vector<std::pair<int, char> >
. The scope operator ::
is then used to let you access class items.
Some other languages don't bother making a distinction between member and class access operators (.
and ::
). C++ has both largely for historical reasons related to C.
Upvotes: 2
Reputation: 146998
The long and short is, it's because C has separate namespaces for types and variables, which means you can construct scenarios where it would be impossible to access members due to ambiguity in C++ if .
could be used to access both member and type in this fashion. And changing the namespacing rules would break compatiblity with legal C code.
struct s1 { typedef int X; };
struct s2 { void X(); };
typedef struct s1 X;
struct s2 X;
int main() {
X.X();
}
Now what? You can't tell from context what X.X is supposed to be.
That's why .
and ::
are in the language- X.X()
refers to a member function call, and X::X
refers to a type.
Upvotes: 9
Reputation: 13708
Because operators .
and ->
are for member access(usually). You can't access anything abstract with it, only tangible objects. And type is an abstract thing. So you have to access it with ::
Upvotes: 0