Michael Tsang
Michael Tsang

Reputation: 781

Why is container.value_type illegal in C++

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

Answers (3)

Peter Bloomfield
Peter Bloomfield

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

Puppy
Puppy

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

ixSci
ixSci

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

Related Questions