Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ using declaration and function overload

Tags:

c++

  1 #include <iostream>
  2 
  3 namespace primerlib {
  4     void compute() { std::cout << "primerlib::print()" << std:: endl; }
  5     void compute(const void *p) { std::cout << "primerlib::print(const void *p)" << std:: endl; }
  6 }
  7 
  8 //using primerlib::compute;
  9 //using namespace primerlib;
 10 void compute(int a) { std::cout << "::compute(int)" << std:: endl; }
 11 void compute(double d, double dd=3.4) { std::cout << "primerlib::compute(d, d)" << std:: endl; }
 12 void compute(char* p, char* p1 = 0) { std::cout << "primerlib::compute(char*, char*)" << std:: endl; }
 13 
 14 int main(void)
 15 {
 16     using primerlib::compute;
 17     //using namespace primerlib;
 18     compute(0);
 19     return 0;
 20 }

output:

primerlib::print(const void *p)

my question is why it didn't call the global compute(int) one ? If I use using directive in line 17 and it will call the compute(int) one. Your help will be really appreciated.

like image 362
ponypaver Avatar asked Aug 28 '15 07:08

ponypaver


People also ask

Can you do function overloading in C?

And C doesn't support Function Overloading.

Why C does not support method overloading?

Function overloading is a feature of Object Oriented programming languages like Java and C++. As we know, C is not an Object Oriented programming language. Therefore, C does not support function overloading.

What is function overloading explain with example in C?

When a function name is overloaded with different jobs it is called Function Overloading. In Function Overloading “Function” name should be the same and the arguments should be different. Function overloading can be considered as an example of a polymorphism feature in C++.

Can static member function be overloaded?

Member functions can't be overloaded solely because one is static and the other isn't static .


2 Answers

That's because using namespace X and using X::Y work differently. When you use using namespace X, everything that is in that namespace is considered during the name lookup. Consider the following example:

namespace A
{
    void foo(int){}
}

namespace B
{
    void foo(int){}
}

using namespace A;
using namespace B;

int main()
{
    foo(1);
}

Here, both A and B members will be considered during the name lookup, and you will have the call of overloaded foo(int) is ambiguous error, because the compiler fails to decide which of the two functions to use, since they are identical. The using X::Y syntax is meant to solve this problem. When you use it, you tell the compiler to only use the Y found in X namespace, without considering anything else. Let's add it to the above example:

namespace A
{
    void foo(int){}
}

namespace B
{
    void foo(int){}
}

using namespace A;
using namespace B;


int main()
{
    using A::foo;  
    foo(1);
}

Here we tell the compiler to use the instance of foo found in the A namespace, and ignore any other foos that are in scope. So, in your example you are telling the compiler to only use primerlib::compute, and you will have to use ::compute() if you want to to access the functions from the global scope, and call the compute(int).

like image 176
SingerOfTheFall Avatar answered Sep 19 '22 18:09

SingerOfTheFall


using primerlib::compute;

this is a using declaration. When you use it, it is as if a name is declared at the location of using declaration. You can bring back global foo by adding using ::foo; (or calling it with global scope ::foo(0); and you will see ::compute(int) in output.

The fact that in your example compiler is not finding global foo declaration, is because this is how name lookup works - it searches enclosing scopes and stopes once a name was found.

For more reference on using declaration see: http://en.cppreference.com/w/cpp/language/namespace#Using-declarations

[edit]

I misunderstood your question, in line 17 you have 'using directive', it behaves differently from using declaration, it does not introduce name in nearest enclosing declarative region (in your case its main function), but adds names to nearest enclosing namespace - in this cast it is global namespace. For more reference: http://en.cppreference.com/w/cpp/language/namespace#Using-directives:

Using-directives are allowed only in namespace scope and in block scope. From the point of view of unqualified name lookup of any name after a using-directive and until the end of the scope in which it appears, every name from namespace-name is visible as if it were declared in the nearest enclosing namespace which contains both the using-directive and namespace-name.

Using-directive does not add any names to the declarative region in which it appears (unlike the using-declaration), and thus does not prevent identical names from being declared.

like image 37
marcinj Avatar answered Sep 20 '22 18:09

marcinj