Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 925
Michael Tsang Avatar asked Oct 25 '25 14:10

Michael Tsang


2 Answers

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.

like image 154
Puppy Avatar answered Oct 28 '25 03:10

Puppy


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.

like image 40
Peter Bloomfield Avatar answered Oct 28 '25 05:10

Peter Bloomfield