0

A question dawned on me lately: Why bother having the scope resolution operator (::) when the usage of the dot operator (.) doesn't clash with the former?

Like,

namespace my_module
{
    const int insane_constant = 69;
    int some_threshold = 100;
}

In order to access some_threshold, one would write my_module::some_threshold. But the thing is the left hand side of :: must be a namespace or a class, as far as I know, while that of the . can never be a namespace or a class. Moreover, the order of :: is higher than ., which is really pointless in my opinion. Why make 2 distinct operators, both of which cannot be overloaded, with use cases can be covered with just one? I'm having a hard time finding any satisfying answer, so any clue on this matter is much appriciated.

  • Scopes have two main roles : namespace scopes for name lookup and normal scope for determination of lifecycles of variables (and functions). And there doesn't need to be something of the lefthand side of ::, ::CoInitializeEx for example use CoInitializeEx from the global namespace (usually legacy API's) – Pepijn Kramer Oct 30 '22 at 11:45
  • @PepijnKramer Yeah I know, but if you write .CoInitializeEx there's still no ambiguity regarding the meaning of '.' used here: it must be a global scope resolution operator, and it doesn't make sense to have .somthing to refer to a member of an object – Dyn Pallomah Oct 30 '22 at 11:50
  • 1
    . and :: do totally different things. :: works on types, . works on instances of types. And that's a big difference – Pepijn Kramer Oct 30 '22 at 11:51
  • I don't think it's a bad question. Opinion-based at worst. AFAIK, both C# and Java use a dot `.` for namespaces (or packages for Java I guess). Though I'm no expert in either. – Nelfeal Oct 30 '22 at 11:55
  • the compiler should know when it is dealing with namespaces, types, or objects etc. so why seperate these main use cases into 2 operators? – Dyn Pallomah Oct 30 '22 at 11:56
  • @ThomasWeller Would you write `for (int i\n i < s\n ++i)`? I wouldn't. And `int x = 69` is definitely not the same thing as `#define x 69`. As for curly braces vs indentation, I think a lot of people who hate Python for exactly that reason can tell you. – Nelfeal Oct 30 '22 at 11:57
  • @Nelfeal: If I would or if I want or if I have to isn't my choice. It's defined by the language. – Thomas Weller Oct 30 '22 at 12:04

4 Answers4

1

Consider the following code:

#include <iostream>
namespace my_module
{
    const int insane_constant = 69;
}
class C{
    public:
    int insane_constant; // actually not constant, but for the example's sake
};
int main(){
  C my_module;
  my_module.insane_constant = my_module::insane_constant;
  std::cout << my_module.insane_constant;
}

How would you distinguish my_module. from my_module:: here?

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
0

You can't replace one with the other.
Example:

namespace A
{
    int x = 0;
    struct X { int x = 1; } A;
    void f()
    {
        std::cout << A.x
                  << A::x
                  << std::endl;
    }
}


int main()
{
    A::f();
}

prints "10".

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
0

Both operators have completely different purposes.

In particular, :: is for referring to a member of a scope while operator. is for referring to a member of an object.

That is, operator:: works on scope while operator. works on objects.

For instance, a classname::membername refers to the member of a class which has a class scope associated with it. On the other hand, object.membername refers to the member of the object object.

Note that not all scopes can be used with operator::. For example, we can refer to a namespace scope's member, class scopes' member(like a static member etc), enumeration' member etc using operator::.

Jason
  • 36,170
  • 5
  • 26
  • 60
0

The other answers showcase situations where :: and . do different things because they act on different entities (scopes vs objects). I'd like to add a bit of motivation behind this choice in the language by comparing it with the situation in C#. Disclaimer: I don't actually use C#, but these points seem obvious when looking into it.

In C#, the "namespace operator" is a dot ., just like the member access operator. However, you cannot have truly global variables: you need a class to put them in. In fact, you cannot even declare a class without a namespace, though this is unrelated to your question.

In C#, there is no possible ambiguity when using the dot between scope and object. Nested namespaces, classes within namespaces, class static variables, enumerators, and so on, are all accessed with a dot.

In C++, that's obviously not the case, and the language took the route of distinguishing between scopes and objects by having two distinct operators.

In plain C, there is no scope resolution, so there is no need for a :: operator. Other languages that make the distinction are Ruby and, apparently, PHP. Among languages that do not make the distinction, you can find for example Python, Go and Java. That last one does have a :: operator, but it's not for scope resolution, it's for forming method references.

In short, C++ has complex scope mechanisms because that's how the language was designed. As a result, it requires two different operators to distinguish scope access and object access.

Nelfeal
  • 12,593
  • 1
  • 20
  • 39