Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C++ parameter scope affect function lookup within a namespace?

This seems a little backwards to me but it works:

#include <iostream>

namespace nTest
{
  struct cTest {};

  void fTest(cTest& x)
  {
    std::cout << "nTest::fTest(cTest&) called" << std::endl;
  }
}

int main(void)
{
  nTest::cTest x;
  fTest(x); //Weird! fTest is resolved since its parameter belongs to nTest.
  return 0;
}

Normally, you would need nTest:: in order to access fTest, but its parameter which belongs to nTest appears to add nTest to the list of possible scopes in which to search for fTest. It seems odd to me that the parameter scope influences the function lookup.

This compiles fine in GCC, but I'm wondering is this usage portable? What is the official definition of this scoping mechanism?

like image 611
Andrew Avatar asked Mar 22 '11 14:03

Andrew


People also ask

What is the scope of using namespace?

A namespace is a declarative region that provides a scope to the identifiers (the names of types, functions, variables, etc) inside it. Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries.

Can you use two namespaces C++?

You can have the same name defined in two different namespaces, but if that is true, then you can only use one of those namespaces at a time. However, this does not mean you cannot use the two namespace in the same program. You can use them each at different times in the same program.

How do you call a namespace function in C++?

Namespaces in C++ You only need to prefix the function you wish to call with namespace_name:: -- similar to how you would call a static member function of a class. Another convenience of namespaces is that they allow you to use the same function name, when it makes sense to do so, to perform multiple different actions.

What is global namespace in C++?

Beginning of C++ only. Global scope or global namespace scope is the outermost namespace scope of a program, in which objects, functions, types and templates can be defined. A name has global namespace scope if the identifier's declaration appears outside of all blocks, namespaces, and classes.


2 Answers

That is ADL (Argument Dependent Lookup) or Koenig Lookup (for the designer of the feature). The purpose of the feature is that in many cases the same namespace will contain types and functions that can be applied to those types, all of which conform the interface. If ADL was not in place, you would have to bring the identifiers into scope with using declarations or you would have to qualify the calls.

This becomes a nightmare since the language allows for operator overloads. Consider the following example:

namespace n {
   struct test {};
   test operator+( test, test const & ); // implemented
};
int main() {
   n::test a,b;
   n::test c = a + b;  //without ADL: c = n::operator+( a, b )
}

While it might seem like an awkward situation, consider that n might be the std namespace, test might be ostream, and operator+ could be operator<<:

int main( int argc, char** ) {
   std::cout << "Hi there, there are " << argc << " arguments" << std::endl;
}

Without ADL, the calls to operator<< would have to be explicit, and moreover you would have to know which of them is implemented as a free function versus a method. Did you know that std::cout << "Hi" is calling a free function and std::cout << 5 is calling a member function? Not many people realize it, and seriously, almost no one cares. ADL hides that from you.

like image 91
David Rodríguez - dribeas Avatar answered Nov 02 '22 05:11

David Rodríguez - dribeas


It is called Koenig aka Argument dependent lookup http://en.wikipedia.org/wiki/Argument-dependent_name_lookup

like image 25
Šimon Tóth Avatar answered Nov 02 '22 05:11

Šimon Tóth